Issue #2822 only allow transfer leader if participant is using shared display
Former-commit-id: af9577548e40397c67f72eb60485ee8de48f169b
This commit is contained in:
parent
8ab1bab974
commit
5250f7a442
5 changed files with 162 additions and 8 deletions
|
@ -36,6 +36,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
|||
* Feb 13, 2014 2751 bclement changed sendObjectToPeer id to VenueParticipant
|
||||
* Feb 13, 2014 2751 njensen Added changeLeader()
|
||||
* Feb 19, 2014 2751 bclement Added isClosed()
|
||||
* Apr 15, 2014 2822 bclement added isSharedDisplayClient()
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -124,4 +125,10 @@ public interface ISharedDisplaySession extends IVenueSession {
|
|||
*/
|
||||
public boolean isClosed();
|
||||
|
||||
/**
|
||||
* @param participant
|
||||
* @return true if the participant is viewing the shared display
|
||||
*/
|
||||
public boolean isSharedDisplayClient(VenueParticipant participant);
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,10 @@ import org.jivesoftware.smack.packet.Presence;
|
|||
import org.jivesoftware.smack.packet.XMPPError;
|
||||
import org.jivesoftware.smack.provider.ProviderManager;
|
||||
import org.jivesoftware.smackx.muc.MultiUserChat;
|
||||
import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
||||
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||
import org.jivesoftware.smackx.pubsub.provider.SubscriptionProvider;
|
||||
import org.jivesoftware.smackx.pubsub.provider.SubscriptionsProvider;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.net.HostAndPort;
|
||||
|
@ -108,6 +112,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
|||
* Apr 09, 2014 2785 mpduff Throw error when not connected and the connection should exist.
|
||||
* Apr 14, 2014 2903 bclement moved from session subpackage to connection, removed password from memory,
|
||||
* moved listeners to own classes, reworked connect/register listeners/login order
|
||||
* Apr 15, 2014 2822 bclement added pubsub owner subscriptions provider registration
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -124,6 +129,19 @@ public class CollaborationConnection implements IEventPublisher {
|
|||
PacketConstants.COLLAB_XMLNS, new SessionPayloadProvider());
|
||||
pm.addIQProvider(PacketConstants.QUERY_ELEMENT_NAME,
|
||||
AuthInfo.AUTH_QUERY_XMLNS, new AuthInfoProvider());
|
||||
/*
|
||||
* smack doesn't support some of the OWNER operations such as getting
|
||||
* all subscriptions on a node. PubSubOperations creates the request
|
||||
* objects for these operations, but the response needs to be parsed.
|
||||
* Here we register the existing smack parsers using the OWNER
|
||||
* namespace.
|
||||
*/
|
||||
pm.addExtensionProvider(
|
||||
PubSubElementType.SUBSCRIPTION.getElementName(),
|
||||
PubSubNamespace.OWNER.getXmlns(), new SubscriptionProvider());
|
||||
pm.addExtensionProvider(
|
||||
PubSubElementType.SUBSCRIPTIONS.getElementName(),
|
||||
PubSubNamespace.OWNER.getXmlns(), new SubscriptionsProvider());
|
||||
}
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
|
|
|
@ -19,9 +19,18 @@
|
|||
**/
|
||||
package com.raytheon.uf.viz.collaboration.comm.provider.session;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.IQ.Type;
|
||||
import org.jivesoftware.smack.packet.Packet;
|
||||
import org.jivesoftware.smackx.pubsub.Node;
|
||||
import org.jivesoftware.smackx.pubsub.NodeExtension;
|
||||
import org.jivesoftware.smackx.pubsub.PubSubElementType;
|
||||
import org.jivesoftware.smackx.pubsub.Subscription;
|
||||
import org.jivesoftware.smackx.pubsub.SubscriptionsExtension;
|
||||
import org.jivesoftware.smackx.pubsub.packet.PubSub;
|
||||
import org.jivesoftware.smackx.pubsub.packet.PubSubNamespace;
|
||||
import org.jivesoftware.smackx.pubsub.packet.SyncPacketSend;
|
||||
|
@ -38,7 +47,8 @@ import com.raytheon.uf.common.xmpp.ext.ChangeAffiliationExtension;
|
|||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 18, 2014 2751 bclement Initial creation
|
||||
* Feb 18, 2014 2751 bclement Initial creation
|
||||
* Apr 15, 2014 2822 bclement added getAllSubscriptions()
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -47,11 +57,14 @@ import com.raytheon.uf.common.xmpp.ext.ChangeAffiliationExtension;
|
|||
*/
|
||||
public class PubSubOperations {
|
||||
|
||||
public static final String PUBSUB_SUBDOMAIN_PREFIX = "pubsub.";
|
||||
|
||||
private PubSubOperations() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Send packet to change affiliation of user on a pubsub topic node
|
||||
* Send packet to change affiliation of user on a pubsub topic node. Calling
|
||||
* client must be owner of node.
|
||||
*
|
||||
* @param conn
|
||||
* @param affiliation
|
||||
|
@ -59,12 +72,56 @@ public class PubSubOperations {
|
|||
*/
|
||||
public static void sendAffiliationPacket(XMPPConnection conn,
|
||||
ChangeAffiliationExtension affiliation) throws XMPPException {
|
||||
PubSub packet = new PubSub();
|
||||
packet.setType(IQ.Type.SET);
|
||||
packet.setTo("pubsub." + conn.getServiceName());
|
||||
packet.setPubSubNamespace(PubSubNamespace.OWNER);
|
||||
packet.addExtension(affiliation);
|
||||
PubSub packet = createOwnerPacket(conn, affiliation, IQ.Type.SET);
|
||||
SyncPacketSend.getReply(conn, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all subscriptions on node. Calling client must be owner of node.
|
||||
*
|
||||
* @param conn
|
||||
* @param n
|
||||
* @return
|
||||
* @throws XMPPException
|
||||
*/
|
||||
public static List<Subscription> getAllSubscriptions(XMPPConnection conn,
|
||||
Node n) throws XMPPException {
|
||||
PubSubElementType type = PubSubElementType.SUBSCRIPTIONS;
|
||||
/*
|
||||
* we need to use the OWNER namespace when we make the request, but we
|
||||
* reuse the provider (parser) for the default namespace for the return.
|
||||
* Use the default namespace to get the extension object from the packet
|
||||
*/
|
||||
String namespace = type.getNamespace().getXmlns();
|
||||
NodeExtension ext = new NodeExtension(type, n.getId());
|
||||
PubSub packet = createOwnerPacket(conn, ext, Type.GET);
|
||||
Packet reply = SyncPacketSend.getReply(conn, packet);
|
||||
SubscriptionsExtension resp = (SubscriptionsExtension) reply
|
||||
.getExtension(type.getElementName(), namespace);
|
||||
if (resp == null){
|
||||
throw new XMPPException(
|
||||
"Subscriptions response missing content for topic: "
|
||||
+ n.getId());
|
||||
}
|
||||
return resp.getSubscriptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create pubsub packet object with owner namespace
|
||||
*
|
||||
* @param conn
|
||||
* @param ext
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private static PubSub createOwnerPacket(XMPPConnection conn,
|
||||
NodeExtension ext, Type type) {
|
||||
PubSub packet = new PubSub();
|
||||
packet.setType(type);
|
||||
packet.setTo(PUBSUB_SUBDOMAIN_PREFIX + conn.getServiceName());
|
||||
packet.setPubSubNamespace(PubSubNamespace.OWNER);
|
||||
packet.addExtension(ext);
|
||||
return packet;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ import java.net.URI;
|
|||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
|
@ -67,6 +69,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.account.ClientAuthManager
|
|||
import com.raytheon.uf.viz.collaboration.comm.provider.connection.CollaborationConnection;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.connection.PeerToPeerCommHelper;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.event.LeaderChangeEvent;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.user.IDConverter;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.user.UserId;
|
||||
import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
||||
|
||||
|
@ -95,6 +98,7 @@ import com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant;
|
|||
* Mar 07, 2014 2848 bclement moved pubsub close logic to closePubSub()
|
||||
* ensure that subscription is setup before joining room
|
||||
* Mar 31, 2014 2899 mpduff Improve error messages.
|
||||
* Apr 15, 2014 2822 bclement added check for other participants being subscribed to topic
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -116,6 +120,8 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
|
||||
private LeafNode topic;
|
||||
|
||||
private final Map<UserId, Boolean> topicSubscribers = new ConcurrentHashMap<UserId, Boolean>();
|
||||
|
||||
private XMPPConnection conn;
|
||||
|
||||
private boolean closed = false;
|
||||
|
@ -624,6 +630,36 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
PubSubOperations.sendAffiliationPacket(conn, affiliation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param user
|
||||
* @return true if user has a subscription to the session topic
|
||||
* @throws XMPPException
|
||||
*/
|
||||
private boolean isSubscribedToTopic(UserId user)
|
||||
throws XMPPException {
|
||||
Boolean rval = topicSubscribers.get(user);
|
||||
if (rval == null) {
|
||||
synchronized (topicSubscribers) {
|
||||
List<Subscription> subs = PubSubOperations.getAllSubscriptions(
|
||||
conn, topic);
|
||||
for (Subscription sub : subs) {
|
||||
topicSubscribers.put(IDConverter.convertFrom(sub.getJid()),
|
||||
true);
|
||||
}
|
||||
}
|
||||
rval = topicSubscribers.get(user);
|
||||
if (rval == null) {
|
||||
/*
|
||||
* userid object hash includes resource, cache as a client that
|
||||
* doesn't use topic
|
||||
*/
|
||||
topicSubscribers.put(user, false);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeLeader(VenueParticipant newLeader)
|
||||
throws CollaborationException {
|
||||
|
@ -645,6 +681,15 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
boolean othersNotified = false;
|
||||
String revokeTarget = null;
|
||||
try {
|
||||
/*
|
||||
* make sure that the new leader is not just in the room, but also
|
||||
* subscribed to the pubsub topic
|
||||
*/
|
||||
if (!isSubscribedToTopic(actualId)) {
|
||||
throw new CollaborationException(
|
||||
"Unable to grant ownership because new leader is not subscribed to session topic");
|
||||
}
|
||||
|
||||
// was formerly the data provider, so hand off pubsub ownership
|
||||
grantTopicOwnership(newLeaderId);
|
||||
topicOwnershipGranted = true;
|
||||
|
@ -670,6 +715,8 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
// 'member' instead of just down to 'admin'
|
||||
revokeTarget = "room";
|
||||
muc.revokeAdmin(account.getNormalizedId());
|
||||
// clear cache of topic subscribers
|
||||
topicSubscribers.clear();
|
||||
} catch (XMPPException e) {
|
||||
if (!othersNotified) {
|
||||
// transaction, attempt to roll back the ownership changes
|
||||
|
@ -713,4 +760,27 @@ public class SharedDisplaySession extends VenueSession implements
|
|||
return closed;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* com.raytheon.uf.viz.collaboration.comm.identity.ISharedDisplaySession
|
||||
* #isSharedDisplayClient
|
||||
* (com.raytheon.uf.viz.collaboration.comm.provider.user.VenueParticipant)
|
||||
*/
|
||||
@Override
|
||||
public boolean isSharedDisplayClient(VenueParticipant participant) {
|
||||
UserId actualId = getVenue().getParticipantUserid(participant);
|
||||
boolean rval = false;
|
||||
if (actualId != null) {
|
||||
try {
|
||||
rval = isSubscribedToTopic(actualId);
|
||||
} catch (XMPPException e) {
|
||||
log.error("Error checking if user is a shared display client",
|
||||
e);
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ import com.raytheon.viz.ui.input.EditableManager;
|
|||
* Mar 06, 2014 2848 bclement moved colormanager update code to session container
|
||||
* Mar 11, 2014 2865 lvenable Added null checks in threads
|
||||
* Mar 18, 2014 2895 njensen Fix lockAction enable/disable logic
|
||||
* Apr 15, 2014 2822 bclement only allow transfer leader if participant is using shared display
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -539,7 +540,8 @@ public class CollaborationSessionView extends SessionView implements
|
|||
.getSelection();
|
||||
VenueParticipant entry = (VenueParticipant) selection
|
||||
.getFirstElement();
|
||||
if (!entry.isSameUser(session.getUserID())) {
|
||||
if (!entry.isSameUser(session.getUserID())
|
||||
&& session.isSharedDisplayClient(entry)) {
|
||||
manager.add(leaderChangeAction);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue