1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-11-26 14:02:06 +01:00

Make EntityCapsManager's node version configurable

Also some cleanup of caps code.
This commit is contained in:
Florian Schmaus 2014-03-11 09:20:55 +01:00
parent 4fb5b85806
commit bd6828db38
2 changed files with 51 additions and 60 deletions

View file

@ -16,9 +16,9 @@
*/ */
package org.jivesoftware.smackx.caps; package org.jivesoftware.smackx.caps;
import org.jivesoftware.smack.AbstractConnectionListener;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.ConnectionCreationListener; import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.Manager;
import org.jivesoftware.smack.PacketInterceptor; import org.jivesoftware.smack.PacketInterceptor;
import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.PacketListener;
@ -66,14 +66,15 @@ import java.security.NoSuchAlgorithmException;
* Keeps track of entity capabilities. * Keeps track of entity capabilities.
* *
* @author Florian Schmaus * @author Florian Schmaus
* @see <a href="http://www.xmpp.org/extensions/xep-0115.html">XEP-0115: Entity Capabilities</a>
*/ */
public class EntityCapsManager extends Manager { public class EntityCapsManager extends Manager {
public static final String NAMESPACE = "http://jabber.org/protocol/caps"; public static final String NAMESPACE = "http://jabber.org/protocol/caps";
public static final String ELEMENT = "c"; public static final String ELEMENT = "c";
private static final String ENTITY_NODE = "http://www.igniterealtime.org/projects/smack";
private static final Map<String, MessageDigest> SUPPORTED_HASHES = new HashMap<String, MessageDigest>(); private static final Map<String, MessageDigest> SUPPORTED_HASHES = new HashMap<String, MessageDigest>();
private static String DEFAULT_ENTITY_NODE = "http://www.igniterealtime.org/projects/smack";
protected static EntityCapsPersistentCache persistentCache; protected static EntityCapsPersistentCache persistentCache;
@ -82,6 +83,12 @@ public class EntityCapsManager extends Manager {
private static Map<XMPPConnection, EntityCapsManager> instances = Collections private static Map<XMPPConnection, EntityCapsManager> instances = Collections
.synchronizedMap(new WeakHashMap<XMPPConnection, EntityCapsManager>()); .synchronizedMap(new WeakHashMap<XMPPConnection, EntityCapsManager>());
private static final PacketFilter PRESENCES_WITH_CAPS = new AndFilter(new PacketTypeFilter(Presence.class), new PacketExtensionFilter(
ELEMENT, NAMESPACE));
private static final PacketFilter PRESENCES_WITHOUT_CAPS = new AndFilter(new PacketTypeFilter(Presence.class), new NotFilter(new PacketExtensionFilter(
ELEMENT, NAMESPACE)));
private static final PacketFilter PRESENCES = new PacketTypeFilter(Presence.class);
/** /**
* Map of (node + '#" + hash algorithm) to DiscoverInfo data * Map of (node + '#" + hash algorithm) to DiscoverInfo data
*/ */
@ -110,11 +117,14 @@ public class EntityCapsManager extends Manager {
} }
} }
private ServiceDiscoveryManager sdm; /**
private boolean entityCapsEnabled; * Set the default entity node that will be used for new EntityCapsManagers
private String currentCapsVersion; *
private boolean presenceSend = false; * @param entityNode
private Queue<String> lastLocalCapsVersions = new ConcurrentLinkedQueue<String>(); */
public static void setDefaultEntityNode(String entityNode) {
DEFAULT_ENTITY_NODE = entityNode;
}
/** /**
* Add DiscoverInfo to the database. * Add DiscoverInfo to the database.
@ -219,31 +229,31 @@ public class EntityCapsManager extends Manager {
((Cache) caps).setMaxCacheSize(maxCacheSize); ((Cache) caps).setMaxCacheSize(maxCacheSize);
} }
private ServiceDiscoveryManager sdm;
private boolean entityCapsEnabled;
private String currentCapsVersion;
private boolean presenceSend = false;
private Queue<String> lastLocalCapsVersions = new ConcurrentLinkedQueue<String>();
/**
* The entity node String used by this EntityCapsManager instance.
*/
private String entityNode = DEFAULT_ENTITY_NODE;
private EntityCapsManager(XMPPConnection connection) { private EntityCapsManager(XMPPConnection connection) {
super(connection); super(connection);
this.sdm = ServiceDiscoveryManager.getInstanceFor(connection); this.sdm = ServiceDiscoveryManager.getInstanceFor(connection);
instances.put(connection, this); instances.put(connection, this);
connection.addConnectionListener(new ConnectionListener() { connection.addConnectionListener(new AbstractConnectionListener() {
@Override
public void connectionClosed() { public void connectionClosed() {
presenceSend = false; presenceSend = false;
} }
@Override
public void connectionClosedOnError(Exception e) { public void connectionClosedOnError(Exception e) {
presenceSend = false; presenceSend = false;
} }
public void reconnectionFailed(Exception e) {
// ignore
}
public void reconnectingIn(int seconds) {
// ignore
}
public void reconnectionSuccessful() {
// ignore
}
}); });
// This calculates the local entity caps version // This calculates the local entity caps version
@ -252,8 +262,6 @@ public class EntityCapsManager extends Manager {
if (autoEnableEntityCaps) if (autoEnableEntityCaps)
enableEntityCaps(); enableEntityCaps();
PacketFilter packetFilter = new AndFilter(new PacketTypeFilter(Presence.class), new PacketExtensionFilter(
ELEMENT, NAMESPACE));
connection.addPacketListener(new PacketListener() { connection.addPacketListener(new PacketListener() {
// Listen for remote presence stanzas with the caps extension // Listen for remote presence stanzas with the caps extension
// If we receive such a stanza, record the JID and nodeVer // If we receive such a stanza, record the JID and nodeVer
@ -276,10 +284,8 @@ public class EntityCapsManager extends Manager {
jidCaps.put(from, new NodeVerHash(node, ver, hash)); jidCaps.put(from, new NodeVerHash(node, ver, hash));
} }
}, packetFilter); }, PRESENCES_WITH_CAPS);
packetFilter = new AndFilter(new PacketTypeFilter(Presence.class), new NotFilter(new PacketExtensionFilter(
ELEMENT, NAMESPACE)));
connection.addPacketListener(new PacketListener() { connection.addPacketListener(new PacketListener() {
@Override @Override
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
@ -288,30 +294,28 @@ public class EntityCapsManager extends Manager {
String from = packet.getFrom(); String from = packet.getFrom();
jidCaps.remove(from); jidCaps.remove(from);
} }
}, packetFilter); }, PRESENCES_WITHOUT_CAPS);
packetFilter = new PacketTypeFilter(Presence.class);
connection.addPacketSendingListener(new PacketListener() { connection.addPacketSendingListener(new PacketListener() {
@Override @Override
public void processPacket(Packet packet) { public void processPacket(Packet packet) {
presenceSend = true; presenceSend = true;
} }
}, packetFilter); }, PRESENCES);
// Intercept presence packages and add caps data when intended. // Intercept presence packages and add caps data when intended.
// XEP-0115 specifies that a client SHOULD include entity capabilities // XEP-0115 specifies that a client SHOULD include entity capabilities
// with every presence notification it sends. // with every presence notification it sends.
PacketFilter capsPacketFilter = new PacketTypeFilter(Presence.class);
PacketInterceptor packetInterceptor = new PacketInterceptor() { PacketInterceptor packetInterceptor = new PacketInterceptor() {
public void interceptPacket(Packet packet) { public void interceptPacket(Packet packet) {
if (!entityCapsEnabled) if (!entityCapsEnabled)
return; return;
CapsExtension caps = new CapsExtension(ENTITY_NODE, getCapsVersion(), "sha-1"); CapsExtension caps = new CapsExtension(entityNode, getCapsVersion(), "sha-1");
packet.addExtension(caps); packet.addExtension(caps);
} }
}; };
connection.addPacketInterceptor(packetInterceptor, capsPacketFilter); connection.addPacketInterceptor(packetInterceptor, PRESENCES);
// It's important to do this as last action. Since it changes the // It's important to do this as last action. Since it changes the
// behavior of the SDM in some ways // behavior of the SDM in some ways
sdm.setEntityCapsManager(this); sdm.setEntityCapsManager(this);
@ -330,14 +334,14 @@ public class EntityCapsManager extends Manager {
return entityCapsManager; return entityCapsManager;
} }
public void enableEntityCaps() { public synchronized void enableEntityCaps() {
// Add Entity Capabilities (XEP-0115) feature node. // Add Entity Capabilities (XEP-0115) feature node.
sdm.addFeature(NAMESPACE); sdm.addFeature(NAMESPACE);
updateLocalEntityCaps(); updateLocalEntityCaps();
entityCapsEnabled = true; entityCapsEnabled = true;
} }
public void disableEntityCaps() { public synchronized void disableEntityCaps() {
entityCapsEnabled = false; entityCapsEnabled = false;
sdm.removeFeature(NAMESPACE); sdm.removeFeature(NAMESPACE);
} }
@ -346,6 +350,11 @@ public class EntityCapsManager extends Manager {
return entityCapsEnabled; return entityCapsEnabled;
} }
public void setEntityNode(String entityNode) {
this.entityNode = entityNode;
updateLocalEntityCaps();
}
/** /**
* Remove a record telling what entity caps node a user has. * Remove a record telling what entity caps node a user has.
* *
@ -374,7 +383,7 @@ public class EntityCapsManager extends Manager {
* @return the local NodeVer * @return the local NodeVer
*/ */
public String getLocalNodeVer() { public String getLocalNodeVer() {
return ENTITY_NODE + '#' + getCapsVersion(); return entityNode + '#' + getCapsVersion();
} }
/** /**
@ -414,19 +423,19 @@ public class EntityCapsManager extends Manager {
sdm.addDiscoverInfoTo(discoverInfo); sdm.addDiscoverInfoTo(discoverInfo);
currentCapsVersion = generateVerificationString(discoverInfo, "sha-1"); currentCapsVersion = generateVerificationString(discoverInfo, "sha-1");
addDiscoverInfoByNode(ENTITY_NODE + '#' + currentCapsVersion, discoverInfo); addDiscoverInfoByNode(entityNode + '#' + currentCapsVersion, discoverInfo);
if (lastLocalCapsVersions.size() > 10) { if (lastLocalCapsVersions.size() > 10) {
String oldCapsVersion = lastLocalCapsVersions.poll(); String oldCapsVersion = lastLocalCapsVersions.poll();
sdm.removeNodeInformationProvider(ENTITY_NODE + '#' + oldCapsVersion); sdm.removeNodeInformationProvider(entityNode + '#' + oldCapsVersion);
} }
lastLocalCapsVersions.add(currentCapsVersion); lastLocalCapsVersions.add(currentCapsVersion);
caps.put(currentCapsVersion, discoverInfo); caps.put(currentCapsVersion, discoverInfo);
if (connection != null) if (connection != null)
jidCaps.put(connection.getUser(), new NodeVerHash(ENTITY_NODE, currentCapsVersion, "sha-1")); jidCaps.put(connection.getUser(), new NodeVerHash(entityNode, currentCapsVersion, "sha-1"));
final List<Identity> identities = new LinkedList<Identity>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities()); final List<Identity> identities = new LinkedList<Identity>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities());
sdm.setNodeInformationProvider(ENTITY_NODE + '#' + currentCapsVersion, new NodeInformationProvider() { sdm.setNodeInformationProvider(entityNode + '#' + currentCapsVersion, new NodeInformationProvider() {
List<String> features = sdm.getFeaturesList(); List<String> features = sdm.getFeaturesList();
List<PacketExtension> packetExtensions = sdm.getExtendedInfoAsList(); List<PacketExtension> packetExtensions = sdm.getExtendedInfoAsList();

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2009 Jonas Ådahl, 2011-2013 Florian Schmaus * Copyright © 2009 Jonas Ådahl, 2011-2014 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.jivesoftware.smackx.caps.packet; package org.jivesoftware.smackx.caps.packet;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.PacketExtension;
@ -22,10 +21,7 @@ import org.jivesoftware.smackx.caps.EntityCapsManager;
public class CapsExtension implements PacketExtension { public class CapsExtension implements PacketExtension {
private String node, ver, hash; private final String node, ver, hash;
public CapsExtension() {
}
public CapsExtension(String node, String version, String hash) { public CapsExtension(String node, String version, String hash) {
this.node = node; this.node = node;
@ -45,26 +41,14 @@ public class CapsExtension implements PacketExtension {
return node; return node;
} }
public void setNode(String node) {
this.node = node;
}
public String getVer() { public String getVer() {
return ver; return ver;
} }
public void setVer(String ver) {
this.ver = ver;
}
public String getHash() { public String getHash() {
return hash; return hash;
} }
public void setHash(String hash) {
this.hash = hash;
}
/* /*
* <c xmlns='http://jabber.org/protocol/caps' * <c xmlns='http://jabber.org/protocol/caps'
* hash='sha-1' * hash='sha-1'
@ -73,11 +57,9 @@ public class CapsExtension implements PacketExtension {
* *
*/ */
public String toXML() { public String toXML() {
String xml = "<" + EntityCapsManager.ELEMENT + " xmlns=\"" + EntityCapsManager.NAMESPACE + "\" " + return "<" + EntityCapsManager.ELEMENT + " xmlns=\"" + EntityCapsManager.NAMESPACE + "\" " +
"hash=\"" + hash + "\" " + "hash=\"" + hash + "\" " +
"node=\"" + node + "\" " + "node=\"" + node + "\" " +
"ver=\"" + ver + "\"/>"; "ver=\"" + ver + "\"/>";
return xml;
} }
} }