mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 06:12:05 +01:00
Merge branch '4.4'
This commit is contained in:
commit
525f27abf1
5 changed files with 82 additions and 19 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -540,13 +540,22 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
|
||||||
// If we are able to resume the stream, then don't set
|
// If we are able to resume the stream, then don't set
|
||||||
// connected/authenticated/usingTLS to false since we like to behave like we are still
|
// connected/authenticated/usingTLS to false since we like to behave like we are still
|
||||||
// connected (e.g. sendStanza should not throw a NotConnectedException).
|
// connected (e.g. sendStanza should not throw a NotConnectedException).
|
||||||
if (isSmResumptionPossible() && instant) {
|
if (instant) {
|
||||||
disconnectedButResumeable = true;
|
disconnectedButResumeable = isSmResumptionPossible();
|
||||||
|
if (!disconnectedButResumeable) {
|
||||||
|
// Reset the stream management session id to null, since the stream is no longer resumable. Note that we
|
||||||
|
// keep the unacknowledgedStanzas queue, because we want to resend them when we are reconnected.
|
||||||
|
smSessionId = null;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
disconnectedButResumeable = false;
|
disconnectedButResumeable = false;
|
||||||
// Reset the stream management session id to null, since if the stream is cleanly closed, i.e. sending a closing
|
|
||||||
// stream tag, there is no longer a stream to resume.
|
// Drop the stream management state if this is not an instant shutdown. We send
|
||||||
smSessionId = null;
|
// a </stream> close tag and now the stream management state is no longer valid.
|
||||||
|
// This also prevents that we will potentially (re-)send any unavailable presence we
|
||||||
|
// may have send, because it got put into the unacknowledged queue and was not acknowledged before the
|
||||||
|
// connection terminated.
|
||||||
|
dropSmState();
|
||||||
// Note that we deliberately do not reset authenticatedConnectionInitiallyEstablishedTimestamp here, so that the
|
// Note that we deliberately do not reset authenticatedConnectionInitiallyEstablishedTimestamp here, so that the
|
||||||
// information is available in the connectionClosedOnError() listeners.
|
// information is available in the connectionClosedOnError() listeners.
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue