CarbonManager.java

  1. /**
  2.  *
  3.  * Copyright 2013-2014 Georg Lukas
  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.carbons;

  18. import java.util.Map;
  19. import java.util.WeakHashMap;

  20. import org.jivesoftware.smack.SmackException;
  21. import org.jivesoftware.smack.SmackException.NoResponseException;
  22. import org.jivesoftware.smack.SmackException.NotConnectedException;
  23. import org.jivesoftware.smack.XMPPConnection;
  24. import org.jivesoftware.smack.ConnectionCreationListener;
  25. import org.jivesoftware.smack.Manager;
  26. import org.jivesoftware.smack.StanzaListener;
  27. import org.jivesoftware.smack.XMPPConnectionRegistry;
  28. import org.jivesoftware.smack.XMPPException;
  29. import org.jivesoftware.smack.XMPPException.XMPPErrorException;
  30. import org.jivesoftware.smack.packet.IQ;
  31. import org.jivesoftware.smack.packet.Message;
  32. import org.jivesoftware.smack.packet.Stanza;
  33. import org.jivesoftware.smackx.carbons.packet.CarbonExtension;
  34. import org.jivesoftware.smackx.carbons.packet.Carbon;
  35. import org.jivesoftware.smackx.carbons.packet.CarbonExtension.Private;
  36. import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;

  37. /**
  38.  * Packet extension for XEP-0280: Message Carbons. This class implements
  39.  * the manager for registering {@link CarbonExtension} support, enabling and disabling
  40.  * message carbons.
  41.  *
  42.  * You should call enableCarbons() before sending your first undirected
  43.  * presence.
  44.  *
  45.  * @author Georg Lukas
  46.  */
  47. public class CarbonManager extends Manager {

  48.     private static Map<XMPPConnection, CarbonManager> INSTANCES = new WeakHashMap<XMPPConnection, CarbonManager>();

  49.     static {
  50.         XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
  51.             public void connectionCreated(XMPPConnection connection) {
  52.                 getInstanceFor(connection);
  53.             }
  54.         });
  55.     }
  56.    
  57.     private volatile boolean enabled_state = false;

  58.     private CarbonManager(XMPPConnection connection) {
  59.         super(connection);
  60.         ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
  61.         sdm.addFeature(CarbonExtension.NAMESPACE);
  62.     }

  63.     /**
  64.      * Obtain the CarbonManager responsible for a connection.
  65.      *
  66.      * @param connection the connection object.
  67.      *
  68.      * @return a CarbonManager instance
  69.      */
  70.     public static synchronized CarbonManager getInstanceFor(XMPPConnection connection) {
  71.         CarbonManager carbonManager = INSTANCES.get(connection);

  72.         if (carbonManager == null) {
  73.             carbonManager = new CarbonManager(connection);
  74.             INSTANCES.put(connection, carbonManager);
  75.         }

  76.         return carbonManager;
  77.     }

  78.     private static IQ carbonsEnabledIQ(final boolean new_state) {
  79.         IQ request;
  80.         if (new_state) {
  81.             request = new Carbon.Enable();
  82.         } else {
  83.             request = new Carbon.Disable();
  84.         }
  85.         return request;
  86.     }

  87.     /**
  88.      * Returns true if XMPP Carbons are supported by the server.
  89.      *
  90.      * @return true if supported
  91.      * @throws NotConnectedException
  92.      * @throws XMPPErrorException
  93.      * @throws NoResponseException
  94.      * @throws InterruptedException
  95.      */
  96.     public boolean isSupportedByServer() throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
  97.         return ServiceDiscoveryManager.getInstanceFor(connection()).serverSupportsFeature(CarbonExtension.NAMESPACE);
  98.     }

  99.     /**
  100.      * Notify server to change the carbons state. This method returns
  101.      * immediately and changes the variable when the reply arrives.
  102.      *
  103.      * You should first check for support using isSupportedByServer().
  104.      *
  105.      * @param new_state whether carbons should be enabled or disabled
  106.      * @throws NotConnectedException
  107.      * @throws InterruptedException
  108.      */
  109.     public void sendCarbonsEnabled(final boolean new_state) throws NotConnectedException, InterruptedException {
  110.         IQ setIQ = carbonsEnabledIQ(new_state);

  111.         connection().sendIqWithResponseCallback(setIQ, new StanzaListener() {
  112.             public void processPacket(Stanza packet) {
  113.                 enabled_state = new_state;
  114.             }
  115.         });
  116.     }

  117.     /**
  118.      * Notify server to change the carbons state. This method blocks
  119.      * some time until the server replies to the IQ and returns true on
  120.      * success.
  121.      *
  122.      * You should first check for support using isSupportedByServer().
  123.      *
  124.      * @param new_state whether carbons should be enabled or disabled
  125.      * @throws XMPPErrorException
  126.      * @throws NoResponseException
  127.      * @throws NotConnectedException
  128.      * @throws InterruptedException
  129.      *
  130.      */
  131.     public synchronized void setCarbonsEnabled(final boolean new_state) throws NoResponseException,
  132.                     XMPPErrorException, NotConnectedException, InterruptedException {
  133.         if (enabled_state == new_state)
  134.             return;

  135.         IQ setIQ = carbonsEnabledIQ(new_state);

  136.         connection().createPacketCollectorAndSend(setIQ).nextResultOrThrow();
  137.         enabled_state = new_state;
  138.     }

  139.     /**
  140.      * Helper method to enable carbons.
  141.      *
  142.      * @throws XMPPException
  143.      * @throws SmackException if there was no response from the server.
  144.      * @throws InterruptedException
  145.      */
  146.     public void enableCarbons() throws XMPPException, SmackException, InterruptedException {
  147.         setCarbonsEnabled(true);
  148.     }

  149.     /**
  150.      * Helper method to disable carbons.
  151.      *
  152.      * @throws XMPPException
  153.      * @throws SmackException if there was no response from the server.
  154.      * @throws InterruptedException
  155.      */
  156.     public void disableCarbons() throws XMPPException, SmackException, InterruptedException {
  157.         setCarbonsEnabled(false);
  158.     }

  159.     /**
  160.      * Check if carbons are enabled on this connection.
  161.      */
  162.     public boolean getCarbonsEnabled() {
  163.         return this.enabled_state;
  164.     }

  165.     /**
  166.      * Mark a message as "private", so it will not be carbon-copied.
  167.      *
  168.      * @param msg Message object to mark private
  169.      * @deprecated use {@link Private#addTo(Message)}
  170.      */
  171.     @Deprecated
  172.     public static void disableCarbons(Message msg) {
  173.         msg.addExtension(Private.INSTANCE);
  174.     }
  175. }