RosterExchangeManager.java

  1. /**
  2.  *
  3.  * Copyright 2003-2007 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.xroster;

  18. import java.lang.ref.WeakReference;
  19. import java.util.Collections;
  20. import java.util.HashSet;
  21. import java.util.Iterator;
  22. import java.util.Map;
  23. import java.util.Set;
  24. import java.util.WeakHashMap;

  25. import org.jivesoftware.smack.StanzaListener;
  26. import org.jivesoftware.smack.SmackException.NotConnectedException;
  27. import org.jivesoftware.smack.XMPPConnection;
  28. import org.jivesoftware.smack.filter.StanzaExtensionFilter;
  29. import org.jivesoftware.smack.filter.StanzaFilter;
  30. import org.jivesoftware.smack.packet.Message;
  31. import org.jivesoftware.smack.packet.Stanza;
  32. import org.jivesoftware.smack.roster.Roster;
  33. import org.jivesoftware.smack.roster.RosterEntry;
  34. import org.jivesoftware.smack.roster.RosterGroup;
  35. import org.jivesoftware.smackx.xroster.packet.RosterExchange;
  36. import org.jxmpp.jid.Jid;

  37. /**
  38.  *
  39.  * Manages Roster exchanges. A RosterExchangeManager provides a high level access to send
  40.  * rosters, roster groups and roster entries to XMPP clients. It also provides an easy way
  41.  * to hook up custom logic when entries are received from another XMPP client through
  42.  * RosterExchangeListeners.
  43.  *
  44.  * @author Gaston Dombiak
  45.  */
  46. public class RosterExchangeManager {

  47.     public final static String NAMESPACE = "jabber:x:roster";
  48.     public final static String ELEMENT = "x";

  49.     private final static Map<XMPPConnection, RosterExchangeManager> INSTANCES = new WeakHashMap<>();

  50.     private final static StanzaFilter PACKET_FILTER = new StanzaExtensionFilter(ELEMENT, NAMESPACE);

  51.     private final Set<RosterExchangeListener> rosterExchangeListeners = Collections.synchronizedSet(new HashSet<RosterExchangeListener>());

  52.     private final WeakReference<XMPPConnection> weakRefConnection;
  53.     private final StanzaListener packetListener;

  54.     public synchronized static RosterExchangeManager getInstanceFor(XMPPConnection connection) {
  55.         RosterExchangeManager rosterExchangeManager = INSTANCES.get(connection);
  56.         if (rosterExchangeManager == null) {
  57.             rosterExchangeManager = new RosterExchangeManager(connection);
  58.             INSTANCES.put(connection, rosterExchangeManager);
  59.         }
  60.         return rosterExchangeManager;
  61.     }

  62.     /**
  63.      * Creates a new roster exchange manager.
  64.      *
  65.      * @param connection an XMPPConnection which is used to send and receive messages.
  66.      */
  67.     public RosterExchangeManager(XMPPConnection connection) {
  68.         weakRefConnection = new WeakReference<XMPPConnection>(connection);
  69.         // Listens for all roster exchange packets and fire the roster exchange listeners.
  70.         packetListener = new StanzaListener() {
  71.             public void processPacket(Stanza packet) {
  72.                 Message message = (Message) packet;
  73.                 RosterExchange rosterExchange =
  74.                     (RosterExchange) message.getExtension(ELEMENT, NAMESPACE);
  75.                 // Fire event for roster exchange listeners
  76.                 fireRosterExchangeListeners(message.getFrom(), rosterExchange.getRosterEntries());
  77.             }
  78.         };
  79.         connection.addAsyncStanzaListener(packetListener, PACKET_FILTER);
  80.     }

  81.     /**
  82.      * Adds a listener to roster exchanges. The listener will be fired anytime roster entries
  83.      * are received from remote XMPP clients.
  84.      *
  85.      * @param rosterExchangeListener a roster exchange listener.
  86.      */
  87.     public void addRosterListener(RosterExchangeListener rosterExchangeListener) {
  88.         rosterExchangeListeners.add(rosterExchangeListener);
  89.     }

  90.     /**
  91.      * Removes a listener from roster exchanges. The listener will be fired anytime roster
  92.      * entries are received from remote XMPP clients.
  93.      *
  94.      * @param rosterExchangeListener a roster exchange listener..
  95.      */
  96.     public void removeRosterListener(RosterExchangeListener rosterExchangeListener) {
  97.         rosterExchangeListeners.remove(rosterExchangeListener);
  98.     }

  99.     /**
  100.      * Sends a roster to userID. All the entries of the roster will be sent to the
  101.      * target user.
  102.      *
  103.      * @param roster the roster to send
  104.      * @param targetUserID the user that will receive the roster entries
  105.      * @throws NotConnectedException
  106.      * @throws InterruptedException
  107.      */
  108.     public void send(Roster roster, Jid targetUserID) throws NotConnectedException, InterruptedException {
  109.         // Create a new message to send the roster
  110.         Message msg = new Message(targetUserID);
  111.         // Create a RosterExchange Package and add it to the message
  112.         RosterExchange rosterExchange = new RosterExchange(roster);
  113.         msg.addExtension(rosterExchange);

  114.         XMPPConnection connection = weakRefConnection.get();
  115.         // Send the message that contains the roster
  116.         connection.sendStanza(msg);
  117.     }

  118.     /**
  119.      * Sends a roster entry to userID.
  120.      *
  121.      * @param rosterEntry the roster entry to send
  122.      * @param targetUserID the user that will receive the roster entries
  123.      * @throws NotConnectedException
  124.      * @throws InterruptedException
  125.      */
  126.     public void send(RosterEntry rosterEntry, Jid targetUserID) throws NotConnectedException, InterruptedException {
  127.         // Create a new message to send the roster
  128.         Message msg = new Message(targetUserID);
  129.         // Create a RosterExchange Package and add it to the message
  130.         RosterExchange rosterExchange = new RosterExchange();
  131.         rosterExchange.addRosterEntry(rosterEntry);
  132.         msg.addExtension(rosterExchange);

  133.         XMPPConnection connection = weakRefConnection.get();
  134.         // Send the message that contains the roster
  135.         connection.sendStanza(msg);
  136.     }

  137.     /**
  138.      * Sends a roster group to userID. All the entries of the group will be sent to the
  139.      * target user.
  140.      *
  141.      * @param rosterGroup the roster group to send
  142.      * @param targetUserID the user that will receive the roster entries
  143.      * @throws NotConnectedException
  144.      * @throws InterruptedException
  145.      */
  146.     public void send(RosterGroup rosterGroup, Jid targetUserID) throws NotConnectedException, InterruptedException {
  147.         // Create a new message to send the roster
  148.         Message msg = new Message(targetUserID);
  149.         // Create a RosterExchange Package and add it to the message
  150.         RosterExchange rosterExchange = new RosterExchange();
  151.         for (RosterEntry entry : rosterGroup.getEntries()) {
  152.             rosterExchange.addRosterEntry(entry);
  153.         }
  154.         msg.addExtension(rosterExchange);

  155.         XMPPConnection connection = weakRefConnection.get();
  156.         // Send the message that contains the roster
  157.         connection.sendStanza(msg);
  158.     }

  159.     /**
  160.      * Fires roster exchange listeners.
  161.      */
  162.     private void fireRosterExchangeListeners(Jid from, Iterator<RemoteRosterEntry> remoteRosterEntries) {
  163.         RosterExchangeListener[] listeners = null;
  164.         synchronized (rosterExchangeListeners) {
  165.             listeners = new RosterExchangeListener[rosterExchangeListeners.size()];
  166.             rosterExchangeListeners.toArray(listeners);
  167.         }
  168.         for (int i = 0; i < listeners.length; i++) {
  169.             listeners[i].entriesReceived(from, remoteRosterEntries);
  170.         }
  171.     }
  172. }