1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-22 14:22:05 +01:00

Merge pull request #427 from Flowdalic/elements

Add XmppElementUtil.castOrThrow()
This commit is contained in:
Florian Schmaus 2020-08-29 16:38:54 +02:00 committed by GitHub
commit 64d3e804a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 14 deletions

View file

@ -90,11 +90,12 @@ public interface StanzaView extends XmlLangElement {
default <E extends ExtensionElement> E getExtension(Class<E> extensionElementClass) { default <E extends ExtensionElement> E getExtension(Class<E> extensionElementClass) {
QName qname = XmppElementUtil.getQNameFor(extensionElementClass); QName qname = XmppElementUtil.getQNameFor(extensionElementClass);
ExtensionElement extensionElement = getExtension(qname); ExtensionElement extensionElement = getExtension(qname);
if (!extensionElementClass.isInstance(extensionElement)) {
if (extensionElement == null) {
return null; return null;
} }
return extensionElementClass.cast(extensionElement); return XmppElementUtil.castOrThrow(extensionElement, extensionElementClass);
} }
/** /**

View file

@ -243,7 +243,11 @@ public final class ProviderManager {
*/ */
public static ExtensionElementProvider<ExtensionElement> getExtensionProvider(String elementName, String namespace) { public static ExtensionElementProvider<ExtensionElement> getExtensionProvider(String elementName, String namespace) {
QName key = getQName(elementName, namespace); QName key = getQName(elementName, namespace);
return extensionProviders.get(key); return getExtensionProvider(key);
}
public static ExtensionElementProvider<ExtensionElement> getExtensionProvider(QName qname) {
return extensionProviders.get(qname);
} }
/** /**

View file

@ -23,17 +23,31 @@ import java.util.logging.Logger;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.FullyQualifiedElement; import org.jivesoftware.smack.packet.FullyQualifiedElement;
import org.jivesoftware.smack.packet.StandardExtensionElement;
import org.jivesoftware.smack.provider.ProviderManager;
import org.jxmpp.util.cache.LruCache;
public class XmppElementUtil { public class XmppElementUtil {
private static final LruCache<Class<? extends FullyQualifiedElement>, QName> CLASS_TO_QNAME_CACHE = new LruCache<>(512);
public static final Logger LOGGER = Logger.getLogger(XmppElementUtil.class.getName()); public static final Logger LOGGER = Logger.getLogger(XmppElementUtil.class.getName());
public static QName getQNameFor(Class<? extends FullyQualifiedElement> fullyQualifiedElement) { public static QName getQNameFor(Class<? extends FullyQualifiedElement> fullyQualifiedElement) {
QName qname = CLASS_TO_QNAME_CACHE.get(fullyQualifiedElement);
if (qname != null) {
return qname;
}
try { try {
Object qnameObject = fullyQualifiedElement.getField("QNAME").get(null); Object qnameObject = fullyQualifiedElement.getField("QNAME").get(null);
if (QName.class.isAssignableFrom(qnameObject.getClass())) { if (QName.class.isAssignableFrom(qnameObject.getClass())) {
return (QName) qnameObject; qname = (QName) qnameObject;
CLASS_TO_QNAME_CACHE.put(fullyQualifiedElement, qname);
return qname;
} }
LOGGER.warning("The QNAME field of " + fullyQualifiedElement + " is not of type QNAME."); LOGGER.warning("The QNAME field of " + fullyQualifiedElement + " is not of type QNAME.");
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
@ -52,24 +66,52 @@ public class XmppElementUtil {
throw new IllegalArgumentException("The " + fullyQualifiedElement + " has no ELEMENT, NAMESPACE or QNAME member. Consider adding QNAME", e); throw new IllegalArgumentException("The " + fullyQualifiedElement + " has no ELEMENT, NAMESPACE or QNAME member. Consider adding QNAME", e);
} }
return new QName(namespace, element); qname = new QName(namespace, element);
CLASS_TO_QNAME_CACHE.put(fullyQualifiedElement, qname);
return qname;
} }
public static <E extends FullyQualifiedElement, R extends FullyQualifiedElement> List<R> getElementsFrom( public static <E extends ExtensionElement> List<E> getElementsFrom(
MultiMap<QName, E> elementMap, Class<R> extensionElementClass) { MultiMap<QName, ExtensionElement> elementMap, Class<E> extensionElementClass) {
QName qname = XmppElementUtil.getQNameFor(extensionElementClass); QName qname = XmppElementUtil.getQNameFor(extensionElementClass);
List<E> extensionElements = elementMap.getAll(qname); List<ExtensionElement> extensionElements = elementMap.getAll(qname);
if (extensionElements.isEmpty()) { if (extensionElements.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<R> res = new ArrayList<>(extensionElements.size()); List<E> res = new ArrayList<>(extensionElements.size());
for (E extensionElement : extensionElements) { for (ExtensionElement extensionElement : extensionElements) {
R e = extensionElementClass.cast(extensionElement); E e = castOrThrow(extensionElement, extensionElementClass);
res.add(e); res.add(e);
} }
return res; return res;
} }
public static <E extends ExtensionElement> E castOrThrow(ExtensionElement extensionElement, Class<E> extensionElementClass) {
if (!extensionElementClass.isInstance(extensionElement)) {
final QName qname = getQNameFor(extensionElementClass);
final String detailMessage;
if (extensionElement instanceof StandardExtensionElement) {
detailMessage = "because there is no according extension element provider registered with ProviderManager for "
+ qname
+ ". WARNING: This indicates a serious problem with your Smack setup, probably causing Smack not being able to properly initialize itself.";
} else {
Object provider = ProviderManager.getExtensionProvider(qname);
detailMessage = "because there is an inconsistency with the provider registered with ProviderManager: the active provider for "
+ qname + " '" + provider.getClass()
+ "' does not return instances of type " + extensionElementClass
+ ", but instead returns instances of type " + extensionElement.getClass() + ".";
}
String message = "Extension element is not of expected class '" + extensionElementClass.getName() + "', "
+ detailMessage;
throw new IllegalStateException(message);
}
return extensionElementClass.cast(extensionElement);
}
} }

View file

@ -18,9 +18,11 @@ package org.jivesoftware.smackx.mam.element;
import java.util.List; import java.util.List;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.Element; import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.MessageView;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
@ -54,6 +56,11 @@ public class MamElements {
*/ */
public static final String ELEMENT = "result"; public static final String ELEMENT = "result";
/**
* The qualified name of the MAM result extension element.
*/
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
/** /**
* id of the result. * id of the result.
*/ */
@ -139,8 +146,8 @@ public class MamElements {
return xml; return xml;
} }
public static MamResultExtension from(Message message) { public static MamResultExtension from(MessageView message) {
return (MamResultExtension) message.getExtensionElement(ELEMENT, NAMESPACE); return message.getExtension(MamResultExtension.class);
} }
} }