Add XMPP.(get|has)Feature(Class|QName) and deprecate (String, String)

This commit is contained in:
Florian Schmaus 2020-07-23 14:32:14 +02:00
parent 91337150e7
commit 329948b442
13 changed files with 78 additions and 18 deletions

View File

@ -760,7 +760,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
user = response.getJid(); user = response.getJid();
xmppServiceDomain = user.asDomainBareJid(); xmppServiceDomain = user.asDomainBareJid();
Session.Feature sessionFeature = getFeature(Session.ELEMENT, Session.NAMESPACE); Session.Feature sessionFeature = getFeature(Session.Feature.class);
// Only bind the session if it's announced as stream feature by the server, is not optional and not disabled // Only bind the session if it's announced as stream feature by the server, is not optional and not disabled
// For more information see http://tools.ietf.org/html/draft-cridland-xmpp-session-01 // For more information see http://tools.ietf.org/html/draft-cridland-xmpp-session-01
if (sessionFeature != null && !sessionFeature.isOptional()) { if (sessionFeature != null && !sessionFeature.isOptional()) {
@ -1904,14 +1904,13 @@ public abstract class AbstractXMPPConnection implements XMPPConnection {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <F extends FullyQualifiedElement> F getFeature(String element, String namespace) { public <F extends FullyQualifiedElement> F getFeature(QName qname) {
QName qname = new QName(namespace, element);
return (F) streamFeatures.get(qname); return (F) streamFeatures.get(qname);
} }
@Override @Override
public boolean hasFeature(String element, String namespace) { public boolean hasFeature(QName qname) {
return getFeature(element, namespace) != null; return streamFeatures.containsKey(qname);
} }
protected void addStreamFeature(FullyQualifiedElement feature) { protected void addStreamFeature(FullyQualifiedElement feature) {

View File

@ -356,7 +356,7 @@ public final class SASLAuthentication {
} }
private List<String> getServerMechanisms() { private List<String> getServerMechanisms() {
Mechanisms mechanisms = connection.getFeature(Mechanisms.ELEMENT, Mechanisms.NAMESPACE); Mechanisms mechanisms = connection.getFeature(Mechanisms.class);
if (mechanisms == null) { if (mechanisms == null) {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -18,6 +18,8 @@ package org.jivesoftware.smack;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException; import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException; import org.jivesoftware.smack.XMPPException.XMPPErrorException;
@ -36,6 +38,7 @@ import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.packet.StanzaFactory; import org.jivesoftware.smack.packet.StanzaFactory;
import org.jivesoftware.smack.util.Consumer; import org.jivesoftware.smack.util.Consumer;
import org.jivesoftware.smack.util.Predicate; import org.jivesoftware.smack.util.Predicate;
import org.jivesoftware.smack.util.XmppElementUtil;
import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityFullJid; import org.jxmpp.jid.EntityFullJid;
@ -576,8 +579,39 @@ public interface XMPPConnection {
* @param element TODO javadoc me please * @param element TODO javadoc me please
* @param namespace TODO javadoc me please * @param namespace TODO javadoc me please
* @return a stanza extensions of the feature or <code>null</code> * @return a stanza extensions of the feature or <code>null</code>
* @deprecated use {@link #getFeature(Class)} instead.
*/ */
<F extends FullyQualifiedElement> F getFeature(String element, String namespace); // TODO: Remove in Smack 4.5.
@Deprecated
default <F extends FullyQualifiedElement> F getFeature(String element, String namespace) {
QName qname = new QName(namespace, element);
return getFeature(qname);
}
/**
* Get the feature stanza extensions for a given stream feature of the
* server, or <code>null</code> if the server doesn't support that feature.
*
* @param <F> {@link ExtensionElement} type of the feature.
* @param qname the qualified name of the XML element of feature.
* @return a stanza extensions of the feature or <code>null</code>
* @since 4.4
*/
<F extends FullyQualifiedElement> F getFeature(QName qname);
/**
* Get the feature stanza extensions for a given stream feature of the
* server, or <code>null</code> if the server doesn't support that feature.
*
* @param <F> {@link ExtensionElement} type of the feature.
* @param featureClass the class of the feature.
* @return a stanza extensions of the feature or <code>null</code>
* @since 4.4
*/
default <F extends FullyQualifiedElement> F getFeature(Class<F> featureClass) {
QName qname = XmppElementUtil.getQNameFor(featureClass);
return getFeature(qname);
}
/** /**
* Return true if the server supports the given stream feature. * Return true if the server supports the given stream feature.
@ -586,7 +620,18 @@ public interface XMPPConnection {
* @param namespace TODO javadoc me please * @param namespace TODO javadoc me please
* @return true if the server supports the stream feature. * @return true if the server supports the stream feature.
*/ */
boolean hasFeature(String element, String namespace); default boolean hasFeature(String element, String namespace) {
QName qname = new QName(namespace, element);
return hasFeature(qname);
}
/**
* Return true if the server supports the given stream feature.
*
* @param qname the qualified name of the XML element of feature.
* @return true if the server supports the stream feature.
*/
boolean hasFeature(QName qname);
/** /**
* Send an IQ request asynchronously. The connection's default reply timeout will be used. * Send an IQ request asynchronously. The connection's default reply timeout will be used.

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014-2015 Florian Schmaus * Copyright © 2014-2020 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.
@ -19,6 +19,8 @@ package org.jivesoftware.smack.compress.packet;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Nonza; import org.jivesoftware.smack.packet.Nonza;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
@ -55,6 +57,7 @@ public class Compress implements Nonza {
public static class Feature implements ExtensionElement { public static class Feature implements ExtensionElement {
public static final String ELEMENT = "compression"; public static final String ELEMENT = "compression";
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
public final List<String> methods; public final List<String> methods;

View File

@ -70,7 +70,7 @@ public class CompressionModule extends ModularXmppClientToServerConnectionModule
return new StateTransitionResult.TransitionImpossibleReason("Stream compression disabled by connection configuration"); return new StateTransitionResult.TransitionImpossibleReason("Stream compression disabled by connection configuration");
} }
Compress.Feature compressFeature = connectionInternal.connection.getFeature(Compress.Feature.ELEMENT, Compress.NAMESPACE); Compress.Feature compressFeature = connectionInternal.connection.getFeature(Compress.Feature.class);
if (compressFeature == null) { if (compressFeature == null) {
return new StateTransitionResult.TransitionImpossibleReason("Stream compression not supported or enabled by service"); return new StateTransitionResult.TransitionImpossibleReason("Stream compression not supported or enabled by service");
} }

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014 Florian Schmaus * Copyright © 2014-2020 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.
@ -21,12 +21,15 @@ import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
public class Mechanisms implements ExtensionElement { public class Mechanisms implements ExtensionElement {
public static final String ELEMENT = "mechanisms"; public static final String ELEMENT = "mechanisms";
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-sasl"; public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-sasl";
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
public final List<String> mechanisms = new LinkedList<String>(); public final List<String> mechanisms = new LinkedList<String>();

View File

@ -17,6 +17,8 @@
package org.jivesoftware.smack.packet; package org.jivesoftware.smack.packet;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
/** /**
@ -44,6 +46,8 @@ public class Session extends SimpleIQ {
public static class Feature implements ExtensionElement { public static class Feature implements ExtensionElement {
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
public static final String OPTIONAL_ELEMENT = "optional"; public static final String OPTIONAL_ELEMENT = "optional";
private final boolean optional; private final boolean optional;

View File

@ -1,6 +1,6 @@
/** /**
* *
* Copyright © 2014-2019 Florian Schmaus * Copyright © 2014-2020 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.
@ -16,6 +16,8 @@
*/ */
package org.jivesoftware.smack.packet; package org.jivesoftware.smack.packet;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smack.util.XmlStringBuilder;
public class StartTls implements Nonza { public class StartTls implements Nonza {
@ -24,6 +26,7 @@ public class StartTls implements Nonza {
public static final String ELEMENT = "starttls"; public static final String ELEMENT = "starttls";
public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-tls"; public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-tls";
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
private final boolean required; private final boolean required;

View File

@ -339,7 +339,7 @@ public final class EntityCapsManager extends Manager {
} }
private void processCapsStreamFeatureIfAvailable(XMPPConnection connection) { private void processCapsStreamFeatureIfAvailable(XMPPConnection connection) {
CapsExtension capsExtension = connection.getFeature( CapsExtension capsExtension = connection.getFeature(
CapsExtension.ELEMENT, CapsExtension.NAMESPACE); CapsExtension.class);
if (capsExtension == null) { if (capsExtension == null) {
return; return;
} }

View File

@ -339,8 +339,7 @@ public final class AccountManager extends Manager {
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
XMPPConnection connection = connection(); XMPPConnection connection = connection();
ExtensionElement extensionElement = connection.getFeature(Registration.Feature.ELEMENT, ExtensionElement extensionElement = connection.getFeature(Registration.Feature.class);
Registration.Feature.NAMESPACE);
if (extensionElement != null) { if (extensionElement != null) {
return true; return true;
} }

View File

@ -19,6 +19,8 @@ package org.jivesoftware.smackx.iqregister.packet;
import java.util.Map; import java.util.Map;
import javax.xml.namespace.QName;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
@ -104,6 +106,8 @@ public class Registration extends IQ {
public static final String ELEMENT = "register"; public static final String ELEMENT = "register";
public static final String NAMESPACE = "http://jabber.org/features/iq-register"; public static final String NAMESPACE = "http://jabber.org/features/iq-register";
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
public static final Feature INSTANCE = new Registration.Feature(); public static final Feature INSTANCE = new Registration.Feature();
private Feature() { private Feature() {

View File

@ -797,7 +797,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
return; return;
} }
Compress.Feature compression = getFeature(Compress.Feature.ELEMENT, Compress.NAMESPACE); Compress.Feature compression = getFeature(Compress.Feature.class);
if (compression == null) { if (compression == null) {
// Server does not support compression // Server does not support compression
return; return;
@ -853,7 +853,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
@Override @Override
protected void afterFeaturesReceived() throws NotConnectedException, InterruptedException, SecurityRequiredByServerException { protected void afterFeaturesReceived() throws NotConnectedException, InterruptedException, SecurityRequiredByServerException {
StartTls startTlsFeature = getFeature(StartTls.ELEMENT, StartTls.NAMESPACE); StartTls startTlsFeature = getFeature(StartTls.class);
if (startTlsFeature != null) { if (startTlsFeature != null) {
if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) { if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) {
SecurityRequiredByServerException smackException = new SecurityRequiredByServerException(); SecurityRequiredByServerException smackException = new SecurityRequiredByServerException();

View File

@ -819,7 +819,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM
@Override @Override
public StateTransitionResult.TransitionImpossible isTransitionToPossible(WalkStateGraphContext walkStateGraphContext) public StateTransitionResult.TransitionImpossible isTransitionToPossible(WalkStateGraphContext walkStateGraphContext)
throws SecurityRequiredByClientException, SecurityRequiredByServerException { throws SecurityRequiredByClientException, SecurityRequiredByServerException {
StartTls startTlsFeature = connectionInternal.connection.getFeature(StartTls.ELEMENT, StartTls.NAMESPACE); StartTls startTlsFeature = connectionInternal.connection.getFeature(StartTls.class);
SecurityMode securityMode = connectionInternal.connection.getConfiguration().getSecurityMode(); SecurityMode securityMode = connectionInternal.connection.getConfiguration().getSecurityMode();
switch (securityMode) { switch (securityMode) {