mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 06:12:05 +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.packet.CapsExtension;
|
||||
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.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Feature;
|
||||
|
@ -128,6 +130,36 @@ public final class EntityCapsManager extends Manager {
|
|||
} catch (NoSuchAlgorithmException e) {
|
||||
// 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
|
||||
* 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);
|
||||
|
||||
if (persistentCache != null)
|
||||
|
@ -365,7 +397,16 @@ public final class EntityCapsManager extends Manager {
|
|||
connection.addStanzaInterceptor(packetInterceptor, PresenceTypeFilter.AVAILABLE);
|
||||
// It's important to do this as last action. Since it changes the
|
||||
// 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) {
|
||||
|
@ -473,7 +514,7 @@ public final class EntityCapsManager extends Manager {
|
|||
* presence is send to inform others about your new Entity Caps node string.
|
||||
*
|
||||
*/
|
||||
public void updateLocalEntityCaps() {
|
||||
private void updateLocalEntityCaps() {
|
||||
XMPPConnection connection = connection();
|
||||
|
||||
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.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||
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.StringUtils;
|
||||
|
||||
import org.jivesoftware.smackx.caps.EntityCapsManager;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo.Identity;
|
||||
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_TYPE = "pc";
|
||||
|
||||
private static final List<DiscoInfoLookupShortcutMechanism> discoInfoLookupShortcutMechanisms = new ArrayList<>(2);
|
||||
|
||||
private static DiscoverInfo.Identity defaultIdentity = new Identity(DEFAULT_IDENTITY_CATEGORY,
|
||||
DEFAULT_IDENTITY_NAME, DEFAULT_IDENTITY_TYPE);
|
||||
|
||||
private final Set<DiscoverInfo.Identity> identities = new HashSet<>();
|
||||
private DiscoverInfo.Identity identity = defaultIdentity;
|
||||
|
||||
private EntityCapsManager capsManager;
|
||||
private final Set<EntityCapabilitiesChangedListener> entityCapabilitiesChangedListeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private static final Map<XMPPConnection, ServiceDiscoveryManager> instances = new WeakHashMap<>();
|
||||
|
||||
|
@ -488,30 +490,19 @@ public final class ServiceDiscoveryManager extends Manager {
|
|||
if (entityID == null)
|
||||
return discoverInfo(null, null);
|
||||
|
||||
// Check if the have it cached in the Entity Capabilities Manager
|
||||
DiscoverInfo info = EntityCapsManager.getDiscoverInfoByUser(entityID);
|
||||
|
||||
if (info != null) {
|
||||
// We were able to retrieve the information from Entity Caps and
|
||||
// avoided a disco request, hurray!
|
||||
return info;
|
||||
synchronized (discoInfoLookupShortcutMechanisms) {
|
||||
for (DiscoInfoLookupShortcutMechanism discoInfoLookupShortcutMechanism : discoInfoLookupShortcutMechanisms) {
|
||||
DiscoverInfo info = discoInfoLookupShortcutMechanism.getDiscoverInfoByUser(this, entityID);
|
||||
if (info != null) {
|
||||
// We were able to retrieve the information from Entity Caps and
|
||||
// avoided a disco request, hurray!
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entity Capabilities
|
||||
*/
|
||||
|
||||
/**
|
||||
* Loads the ServiceDiscoveryManager with an EntityCapsManger that speeds up certain lookups.
|
||||
*
|
||||
* @param manager
|
||||
*/
|
||||
public void setEntityCapsManager(EntityCapsManager manager) {
|
||||
capsManager = manager;
|
||||
public boolean addEntityCapabilitiesChangedListener(EntityCapabilitiesChangedListener entityCapabilitiesChangedListener) {
|
||||
return entityCapabilitiesChangedListeners.add(entityCapabilitiesChangedListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the Entity Capabilities Verification String if EntityCaps is enabled.
|
||||
* Notify the {@link EntityCapabilitiesChangedListener} about changed capabilities.
|
||||
*/
|
||||
private void renewEntityCapsVersion() {
|
||||
if (capsManager != null && capsManager.entityCapsEnabled())
|
||||
capsManager.updateLocalEntityCaps();
|
||||
for (EntityCapabilitiesChangedListener entityCapabilitiesChangedListener : entityCapabilitiesChangedListeners) {
|
||||
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