mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-22 20:12:07 +01:00
Add DiscoInfoLookupShortcutMechanism and EntityCapabilitiesChangedListener
to allow for plugable XEP-0115 like mechanisms. For example XEP-0390.
This commit is contained in:
parent
0e31bc8f73
commit
72de6540b2
4 changed files with 155 additions and 41 deletions
|
@ -59,6 +59,8 @@ import org.jivesoftware.smack.util.stringencoder.Base64;
|
||||||
import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache;
|
import org.jivesoftware.smackx.caps.cache.EntityCapsPersistentCache;
|
||||||
import org.jivesoftware.smackx.caps.packet.CapsExtension;
|
import org.jivesoftware.smackx.caps.packet.CapsExtension;
|
||||||
import org.jivesoftware.smackx.disco.AbstractNodeInformationProvider;
|
import org.jivesoftware.smackx.disco.AbstractNodeInformationProvider;
|
||||||
|
import org.jivesoftware.smackx.disco.DiscoInfoLookupShortcutMechanism;
|
||||||
|
import org.jivesoftware.smackx.disco.EntityCapabilitiesChangedListener;
|
||||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
||||||
|
@ -128,6 +130,36 @@ public final class EntityCapsManager extends Manager {
|
||||||
} catch (NoSuchAlgorithmException e) {
|
} catch (NoSuchAlgorithmException e) {
|
||||||
// Ignore
|
// Ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServiceDiscoveryManager.addDiscoInfoLookupShortcutMechanism(new DiscoInfoLookupShortcutMechanism("XEP-0115: Entity Capabilities", 100) {
|
||||||
|
@Override
|
||||||
|
public DiscoverInfo getDiscoverInfoByUser(ServiceDiscoveryManager serviceDiscoveryManager, Jid jid) {
|
||||||
|
DiscoverInfo info = EntityCapsManager.getDiscoverInfoByUser(jid);
|
||||||
|
if (info != null) {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeVerHash nodeVerHash = getNodeVerHashByJid(jid);
|
||||||
|
if (nodeVerHash == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
info = serviceDiscoveryManager.discoverInfo(jid, nodeVerHash.getNodeVer());
|
||||||
|
} catch (NoResponseException | XMPPErrorException | NotConnectedException | InterruptedException e) {
|
||||||
|
// TODO log
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verifyDiscoverInfoVersion(nodeVerHash.getVer(), nodeVerHash.getHash(), info)) {
|
||||||
|
addDiscoverInfoByNode(nodeVerHash.getNodeVer(), info);
|
||||||
|
} else {
|
||||||
|
// TODO log
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -148,7 +180,7 @@ public final class EntityCapsManager extends Manager {
|
||||||
* @param info
|
* @param info
|
||||||
* DiscoverInfo for the specified node.
|
* DiscoverInfo for the specified node.
|
||||||
*/
|
*/
|
||||||
public static void addDiscoverInfoByNode(String nodeVer, DiscoverInfo info) {
|
static void addDiscoverInfoByNode(String nodeVer, DiscoverInfo info) {
|
||||||
CAPS_CACHE.put(nodeVer, info);
|
CAPS_CACHE.put(nodeVer, info);
|
||||||
|
|
||||||
if (persistentCache != null)
|
if (persistentCache != null)
|
||||||
|
@ -365,7 +397,16 @@ public final class EntityCapsManager extends Manager {
|
||||||
connection.addStanzaInterceptor(packetInterceptor, PresenceTypeFilter.AVAILABLE);
|
connection.addStanzaInterceptor(packetInterceptor, PresenceTypeFilter.AVAILABLE);
|
||||||
// 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.addEntityCapabilitiesChangedListener(new EntityCapabilitiesChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onEntityCapailitiesChanged() {
|
||||||
|
if (!entityCapsEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLocalEntityCaps();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized EntityCapsManager getInstanceFor(XMPPConnection connection) {
|
public static synchronized EntityCapsManager getInstanceFor(XMPPConnection connection) {
|
||||||
|
@ -473,7 +514,7 @@ public final class EntityCapsManager extends Manager {
|
||||||
* presence is send to inform others about your new Entity Caps node string.
|
* presence is send to inform others about your new Entity Caps node string.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void updateLocalEntityCaps() {
|
private void updateLocalEntityCaps() {
|
||||||
XMPPConnection connection = connection();
|
XMPPConnection connection = connection();
|
||||||
|
|
||||||
DiscoverInfo discoverInfo = new DiscoverInfo();
|
DiscoverInfo discoverInfo = new DiscoverInfo();
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.disco;
|
||||||
|
|
||||||
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.Jid;
|
||||||
|
|
||||||
|
public abstract class DiscoInfoLookupShortcutMechanism implements Comparable<DiscoInfoLookupShortcutMechanism> {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final int priority;
|
||||||
|
|
||||||
|
protected DiscoInfoLookupShortcutMechanism(String name, int priority) {
|
||||||
|
this.name = name;
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the priority of this mechanism. Lower values mean higher priority.
|
||||||
|
*
|
||||||
|
* @return the priority of this mechanism.
|
||||||
|
*/
|
||||||
|
public final int getPriority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract DiscoverInfo getDiscoverInfoByUser(ServiceDiscoveryManager serviceDiscoveryManager, Jid jid);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final int compareTo(DiscoInfoLookupShortcutMechanism other) {
|
||||||
|
// Switch to Integer.compare(int, int) once Smack is on Android 19 or higher.
|
||||||
|
Integer ourPriority = getPriority();
|
||||||
|
return ourPriority.compareTo(other.getPriority());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright 2018 Florian Schmaus.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.disco;
|
||||||
|
|
||||||
|
public interface EntityCapabilitiesChangedListener {
|
||||||
|
|
||||||
|
void onEntityCapailitiesChanged();
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
|
|
||||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||||
import org.jivesoftware.smack.Manager;
|
import org.jivesoftware.smack.Manager;
|
||||||
|
@ -44,7 +45,6 @@ import org.jivesoftware.smack.packet.StanzaError;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
|
||||||
import org.jivesoftware.smackx.caps.EntityCapsManager;
|
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||||
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
import org.jivesoftware.smackx.disco.packet.DiscoverItems;
|
||||||
|
@ -74,13 +74,15 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
private static final String DEFAULT_IDENTITY_CATEGORY = "client";
|
private static final String DEFAULT_IDENTITY_CATEGORY = "client";
|
||||||
private static final String DEFAULT_IDENTITY_TYPE = "pc";
|
private static final String DEFAULT_IDENTITY_TYPE = "pc";
|
||||||
|
|
||||||
|
private static final List<DiscoInfoLookupShortcutMechanism> discoInfoLookupShortcutMechanisms = new ArrayList<>(2);
|
||||||
|
|
||||||
private static DiscoverInfo.Identity defaultIdentity = new Identity(DEFAULT_IDENTITY_CATEGORY,
|
private static DiscoverInfo.Identity defaultIdentity = new Identity(DEFAULT_IDENTITY_CATEGORY,
|
||||||
DEFAULT_IDENTITY_NAME, DEFAULT_IDENTITY_TYPE);
|
DEFAULT_IDENTITY_NAME, DEFAULT_IDENTITY_TYPE);
|
||||||
|
|
||||||
private final Set<DiscoverInfo.Identity> identities = new HashSet<>();
|
private final Set<DiscoverInfo.Identity> identities = new HashSet<>();
|
||||||
private DiscoverInfo.Identity identity = defaultIdentity;
|
private DiscoverInfo.Identity identity = defaultIdentity;
|
||||||
|
|
||||||
private EntityCapsManager capsManager;
|
private final Set<EntityCapabilitiesChangedListener> entityCapabilitiesChangedListeners = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
private static final Map<XMPPConnection, ServiceDiscoveryManager> instances = new WeakHashMap<>();
|
private static final Map<XMPPConnection, ServiceDiscoveryManager> instances = new WeakHashMap<>();
|
||||||
|
|
||||||
|
@ -488,30 +490,19 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
if (entityID == null)
|
if (entityID == null)
|
||||||
return discoverInfo(null, null);
|
return discoverInfo(null, null);
|
||||||
|
|
||||||
// Check if the have it cached in the Entity Capabilities Manager
|
synchronized (discoInfoLookupShortcutMechanisms) {
|
||||||
DiscoverInfo info = EntityCapsManager.getDiscoverInfoByUser(entityID);
|
for (DiscoInfoLookupShortcutMechanism discoInfoLookupShortcutMechanism : discoInfoLookupShortcutMechanisms) {
|
||||||
|
DiscoverInfo info = discoInfoLookupShortcutMechanism.getDiscoverInfoByUser(this, entityID);
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
// We were able to retrieve the information from Entity Caps and
|
// We were able to retrieve the information from Entity Caps and
|
||||||
// avoided a disco request, hurray!
|
// avoided a disco request, hurray!
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Try to get the newest node#version if it's known, otherwise null is
|
|
||||||
// returned
|
|
||||||
EntityCapsManager.NodeVerHash nvh = EntityCapsManager.getNodeVerHashByJid(entityID);
|
|
||||||
|
|
||||||
// Discover by requesting the information from the remote entity
|
|
||||||
// Note that wee need to use NodeVer as argument for Node if it exists
|
|
||||||
info = discoverInfo(entityID, nvh != null ? nvh.getNodeVer() : null);
|
|
||||||
|
|
||||||
// If the node version is known, store the new entry.
|
|
||||||
if (nvh != null) {
|
|
||||||
if (EntityCapsManager.verifyDiscoverInfoVersion(nvh.getVer(), nvh.getHash(), info))
|
|
||||||
EntityCapsManager.addDiscoverInfoByNode(nvh.getNodeVer(), info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return info;
|
// Last resort: Standard discovery.
|
||||||
|
return discoverInfo(entityID, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -933,24 +924,29 @@ public final class ServiceDiscoveryManager extends Manager {
|
||||||
return findService(feature, useCache, null, null);
|
return findService(feature, useCache, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public boolean addEntityCapabilitiesChangedListener(EntityCapabilitiesChangedListener entityCapabilitiesChangedListener) {
|
||||||
* Entity Capabilities
|
return entityCapabilitiesChangedListeners.add(entityCapabilitiesChangedListener);
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the ServiceDiscoveryManager with an EntityCapsManger that speeds up certain lookups.
|
|
||||||
*
|
|
||||||
* @param manager
|
|
||||||
*/
|
|
||||||
public void setEntityCapsManager(EntityCapsManager manager) {
|
|
||||||
capsManager = manager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the Entity Capabilities Verification String if EntityCaps is enabled.
|
* Notify the {@link EntityCapabilitiesChangedListener} about changed capabilities.
|
||||||
*/
|
*/
|
||||||
private void renewEntityCapsVersion() {
|
private void renewEntityCapsVersion() {
|
||||||
if (capsManager != null && capsManager.entityCapsEnabled())
|
for (EntityCapabilitiesChangedListener entityCapabilitiesChangedListener : entityCapabilitiesChangedListeners) {
|
||||||
capsManager.updateLocalEntityCaps();
|
entityCapabilitiesChangedListener.onEntityCapailitiesChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addDiscoInfoLookupShortcutMechanism(DiscoInfoLookupShortcutMechanism discoInfoLookupShortcutMechanism) {
|
||||||
|
synchronized (discoInfoLookupShortcutMechanisms) {
|
||||||
|
discoInfoLookupShortcutMechanisms.add(discoInfoLookupShortcutMechanism);
|
||||||
|
Collections.sort(discoInfoLookupShortcutMechanisms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeDiscoInfoLookupShortcutMechanism(DiscoInfoLookupShortcutMechanism discoInfoLookupShortcutMechanism) {
|
||||||
|
synchronized (discoInfoLookupShortcutMechanisms) {
|
||||||
|
discoInfoLookupShortcutMechanisms.remove(discoInfoLookupShortcutMechanism);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue