diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index 246f05eb2..bd3d47554 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -763,7 +763,7 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { user = response.getJid(); 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 // For more information see http://tools.ietf.org/html/draft-cridland-xmpp-session-01 if (sessionFeature != null && !sessionFeature.isOptional()) { @@ -1913,14 +1913,13 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { @SuppressWarnings("unchecked") @Override - public F getFeature(String element, String namespace) { - QName qname = new QName(namespace, element); + public F getFeature(QName qname) { return (F) streamFeatures.get(qname); } @Override - public boolean hasFeature(String element, String namespace) { - return getFeature(element, namespace) != null; + public boolean hasFeature(QName qname) { + return streamFeatures.containsKey(qname); } protected void addStreamFeature(FullyQualifiedElement feature) { diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java index 6c1c31a5d..2e02b5080 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SASLAuthentication.java @@ -356,7 +356,7 @@ public final class SASLAuthentication { } private List getServerMechanisms() { - Mechanisms mechanisms = connection.getFeature(Mechanisms.ELEMENT, Mechanisms.NAMESPACE); + Mechanisms mechanisms = connection.getFeature(Mechanisms.class); if (mechanisms == null) { return Collections.emptyList(); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java index 842007f1e..1d3ca49d1 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/XMPPConnection.java @@ -18,6 +18,8 @@ package org.jivesoftware.smack; import java.util.concurrent.TimeUnit; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; 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.util.Consumer; import org.jivesoftware.smack.util.Predicate; +import org.jivesoftware.smack.util.XmppElementUtil; import org.jxmpp.jid.DomainBareJid; import org.jxmpp.jid.EntityFullJid; @@ -576,8 +579,39 @@ public interface XMPPConnection { * @param element TODO javadoc me please * @param namespace TODO javadoc me please * @return a stanza extensions of the feature or null + * @deprecated use {@link #getFeature(Class)} instead. */ - F getFeature(String element, String namespace); + // TODO: Remove in Smack 4.5. + @Deprecated + default 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 null if the server doesn't support that feature. + * + * @param {@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 null + * @since 4.4 + */ + F getFeature(QName qname); + + /** + * Get the feature stanza extensions for a given stream feature of the + * server, or null if the server doesn't support that feature. + * + * @param {@link ExtensionElement} type of the feature. + * @param featureClass the class of the feature. + * @return a stanza extensions of the feature or null + * @since 4.4 + */ + default F getFeature(Class featureClass) { + QName qname = XmppElementUtil.getQNameFor(featureClass); + return getFeature(qname); + } /** * Return true if the server supports the given stream feature. @@ -586,7 +620,18 @@ public interface XMPPConnection { * @param namespace TODO javadoc me please * @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. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compress/packet/Compress.java b/smack-core/src/main/java/org/jivesoftware/smack/compress/packet/Compress.java index a3ba65245..3a197aab6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compress/packet/Compress.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compress/packet/Compress.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2015 Florian Schmaus + * Copyright © 2014-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (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.List; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.Nonza; import org.jivesoftware.smack.util.XmlStringBuilder; @@ -55,6 +57,7 @@ public class Compress implements Nonza { public static class Feature implements ExtensionElement { public static final String ELEMENT = "compression"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); public final List methods; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModule.java b/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModule.java index ce0dddeea..79bd0a21d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModule.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/compression/CompressionModule.java @@ -70,7 +70,7 @@ public class CompressionModule extends ModularXmppClientToServerConnectionModule 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) { return new StateTransitionResult.TransitionImpossibleReason("Stream compression not supported or enabled by service"); } diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java index 4ef0bcd66..a981589ee 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Mechanisms.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014 Florian Schmaus + * Copyright © 2014-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (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.List; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.util.XmlStringBuilder; public class Mechanisms implements ExtensionElement { public static final String ELEMENT = "mechanisms"; public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-sasl"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); public final List mechanisms = new LinkedList(); diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java index a226b729d..48e0330c6 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/Session.java @@ -17,6 +17,8 @@ package org.jivesoftware.smack.packet; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.util.XmlStringBuilder; /** @@ -44,6 +46,8 @@ public class Session extends SimpleIQ { public static class Feature implements ExtensionElement { + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + public static final String OPTIONAL_ELEMENT = "optional"; private final boolean optional; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StartTls.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StartTls.java index aebb1ad3f..070b287b7 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/packet/StartTls.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StartTls.java @@ -1,6 +1,6 @@ /** * - * Copyright © 2014-2019 Florian Schmaus + * Copyright © 2014-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,8 @@ */ package org.jivesoftware.smack.packet; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.util.XmlStringBuilder; public class StartTls implements Nonza { @@ -24,6 +26,7 @@ public class StartTls implements Nonza { public static final String ELEMENT = "starttls"; 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; diff --git a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java index 6fadfd3a8..bf8a4a224 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramMechanism.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014-2019 Florian Schmaus + * Copyright 2014-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -227,7 +227,7 @@ public abstract class ScramMechanism extends SASLMechanism { authzidPortion = "a=" + authorizationId; } - String cbName = getChannelBindingName(); + String cbName = getGs2CbindFlag(); assert StringUtils.isNotEmpty(cbName); return cbName + ',' + authzidPortion + ","; @@ -244,7 +244,13 @@ public abstract class ScramMechanism extends SASLMechanism { return ByteUtils.concat(gs2Header, cbindData); } - protected String getChannelBindingName() { + /** + * Get the SCRAM GSS-API Channel Binding Flag value. + * + * @return the gs2-cbind-flag value. + * @see RFC 5802 § 6. + */ + protected String getGs2CbindFlag() { // Check if we are using TLS and if a "-PLUS" variant of this mechanism is enabled. Assuming that the "-PLUS" // variants always have precedence before the non-"-PLUS" variants this means that the server did not announce // the "-PLUS" variant, as otherwise we would have tried it. diff --git a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramPlusMechanism.java b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramPlusMechanism.java index 0aa7eee3f..849eee55d 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramPlusMechanism.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/sasl/core/ScramPlusMechanism.java @@ -1,6 +1,6 @@ /** * - * Copyright 2016-2019 Florian Schmaus + * Copyright 2016-2020 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,7 +43,7 @@ public abstract class ScramPlusMechanism extends ScramMechanism { } @Override - protected String getChannelBindingName() { + protected String getGs2CbindFlag() { return "p=tls-server-end-point"; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java index c63471bcb..b776cf8a4 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/caps/EntityCapsManager.java @@ -339,7 +339,7 @@ public final class EntityCapsManager extends Manager { } private void processCapsStreamFeatureIfAvailable(XMPPConnection connection) { CapsExtension capsExtension = connection.getFeature( - CapsExtension.ELEMENT, CapsExtension.NAMESPACE); + CapsExtension.class); if (capsExtension == null) { return; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java index 293cb5cbc..18440c9ce 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/AccountManager.java @@ -339,8 +339,7 @@ public final class AccountManager extends Manager { throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { XMPPConnection connection = connection(); - ExtensionElement extensionElement = connection.getFeature(Registration.Feature.ELEMENT, - Registration.Feature.NAMESPACE); + ExtensionElement extensionElement = connection.getFeature(Registration.Feature.class); if (extensionElement != null) { return true; } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java index e8b9795e4..543106b2d 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/iqregister/packet/Registration.java @@ -19,6 +19,8 @@ package org.jivesoftware.smackx.iqregister.packet; import java.util.Map; +import javax.xml.namespace.QName; + import org.jivesoftware.smack.packet.ExtensionElement; 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 NAMESPACE = "http://jabber.org/features/iq-register"; + public static final QName QNAME = new QName(NAMESPACE, ELEMENT); + public static final Feature INSTANCE = new Registration.Feature(); private Feature() { diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index 52ed8a077..2dbb44a04 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -801,7 +801,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { return; } - Compress.Feature compression = getFeature(Compress.Feature.ELEMENT, Compress.NAMESPACE); + Compress.Feature compression = getFeature(Compress.Feature.class); if (compression == null) { // Server does not support compression return; @@ -857,7 +857,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { @Override protected void afterFeaturesReceived() throws NotConnectedException, InterruptedException, SecurityRequiredByServerException { - StartTls startTlsFeature = getFeature(StartTls.ELEMENT, StartTls.NAMESPACE); + StartTls startTlsFeature = getFeature(StartTls.class); if (startTlsFeature != null) { if (startTlsFeature.required() && config.getSecurityMode() == SecurityMode.disabled) { SecurityRequiredByServerException smackException = new SecurityRequiredByServerException(); diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java index e48c35b25..60ba9fd41 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XmppTcpTransportModule.java @@ -819,7 +819,7 @@ public class XmppTcpTransportModule extends ModularXmppClientToServerConnectionM @Override public StateTransitionResult.TransitionImpossible isTransitionToPossible(WalkStateGraphContext walkStateGraphContext) 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(); switch (securityMode) {