/*
* Jicofo, the Jitsi Conference Focus.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jitsi.impl.protocol.xmpp;
import net.java.sip.communicator.util.*;
import org.jitsi.jicofo.*;
import org.jitsi.protocol.xmpp.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smackx.pubsub.*;
import org.jivesoftware.smackx.pubsub.listener.*;
import java.util.*;
/**
* XMPP Pub-sub node implementation of {@link OperationSetSubscription}.
*
* @author Pawel Domas
*/
public class OpSetSubscriptionImpl
implements OperationSetSubscription,
ItemEventListener
{
/**
* The logger used by this instance.
*/
private final static Logger logger
= Logger.getLogger(OpSetSubscriptionImpl.class);
/**
* The configuration property used to specify address for pub-sub node.
*/
public static final String PUBSUB_ADDRESS_PNAME
= "org.jitsi.focus.pubsub.ADDRESS";
/**
* Smack PubSub manager.
*/
private PubSubManager manager;
/**
* PubSub address used.
*/
private final String pubSubAddress;
/**
* Our JID used for PubSub registration.
*/
private String ourJid;
/**
* The map of PubSub node listeners.
*/
private Map<String, SubscriptionListener> listenerMap
= new HashMap<String, SubscriptionListener>();
/**
* Parent XMPP provider used to hndle the protocol.
*/
private final XmppProtocolProvider parentProvider;
/**
* Creates new instance of {@link OpSetSubscriptionImpl}.
*
* @param parentProvider the XMPP provider instance.
*/
public OpSetSubscriptionImpl(XmppProtocolProvider parentProvider)
{
this.parentProvider = parentProvider;
this.pubSubAddress
= FocusBundleActivator.getConfigService()
.getString(PUBSUB_ADDRESS_PNAME);
}
/**
* Lazy initializer for our JID field(it's not available before provider
* gets connected).
*/
private String getOurJid()
{
if (ourJid == null)
{
this.ourJid = parentProvider.getOurJid();
}
return ourJid;
}
/**
* Lazy initializer for PubSub manager.
*/
private PubSubManager getManager()
{
if (manager == null)
{
manager = new PubSubManager(
parentProvider.getConnection(), pubSubAddress);
}
return manager;
}
/**
* Checks if given <tt>jid</tt> is registered for PubSub updates on given
* <tt>node</tt>.
*/
private boolean isSubscribed(String jid, Node node)
throws XMPPException
{
// FIXME: consider using local flag rather than getting the list
// of subscriptions
for (Subscription subscription : node.getSubscriptions())
{
if (subscription.getJid().equals(jid))
{
return true;
}
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public void subscribe(String node, SubscriptionListener listener)
{
listenerMap.put(node, listener);
PubSubManager manager = getManager();
try
{
Node pubSubNode = manager.getNode(node);
if (!isSubscribed(getOurJid(), pubSubNode))
{
// FIXME: Is it possible that we will be subscribed after
// our connection dies ? If yes we won't add listener here
// and won't receive notifications
pubSubNode.addItemEventListener(this);
pubSubNode.subscribe(parentProvider.getOurJid());
}
}
catch (XMPPException e)
{
logger.error(e.getMessage(), e);
}
}
/**
* {@inheritDoc}
*/
@Override
public void unSubscribe(String node)
{
if (!listenerMap.containsKey(node))
{
logger.warn("No PUBSUB listener for " + node);
return;
}
PubSubManager manager = getManager();
try
{
Node pubSubNode = manager.getNode(node);
if (isSubscribed(getOurJid(), pubSubNode))
{
pubSubNode.unsubscribe(getOurJid());
}
}
catch (XMPPException e)
{
logger.error(e.getMessage(), e);
}
}
/**
* Fired by Smack on PubSub update.
*
* {@inheritDoc}
*/
@Override
public void handlePublishedItems(ItemPublishEvent event)
{
String nodeId = event.getNodeId();
if (logger.isDebugEnabled())
logger.debug("PubSub update for node: " + nodeId);
SubscriptionListener listener = listenerMap.get(nodeId);
if (listener != null)
{
for(Object item : event.getItems())
{
if(!(item instanceof PayloadItem))
continue;
PayloadItem payloadItem = (PayloadItem) item;
listener.onSubscriptionUpdate(nodeId, payloadItem.getPayload());
}
}
}
}