mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-09-27 18:19:33 +02:00
3d4e7938a7
ExtensionElement is now a marker interface that requires all implementation non-abstract classes to carry a static final QNAME field (of type QName). This is verified by a new unit test. Also FullyQualifiedElement is renamed to simply XmlElement. XmlElement is used over ExtensionElement when implementing classes do not statically know the qualified name of the XML elements they represent. In general, XmlElement should be used sparingly, and every XML element should be modeled by its own Java class (implementing ExtensionElement).
370 lines
10 KiB
Java
370 lines
10 KiB
Java
/**
|
|
*
|
|
* Copyright © 2014-2021 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.smack.sm.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.packet.StanzaError;
|
|
import org.jivesoftware.smack.packet.StanzaErrorTextElement;
|
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
|
|
|
public class StreamManagement {
|
|
public static final String NAMESPACE = "urn:xmpp:sm:3";
|
|
|
|
public static final class StreamManagementFeature implements ExtensionElement {
|
|
|
|
public static final String ELEMENT = "sm";
|
|
public static final QName QNAME = new QName(NAMESPACE, ELEMENT);
|
|
|
|
public static final StreamManagementFeature INSTANCE = new StreamManagementFeature();
|
|
|
|
private StreamManagementFeature() {
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return QNAME.getLocalPart();
|
|
}
|
|
|
|
@Override
|
|
public String getNamespace() {
|
|
return QNAME.getNamespaceURI();
|
|
}
|
|
|
|
@Override
|
|
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
|
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
|
|
xml.closeEmptyElement();
|
|
return xml;
|
|
}
|
|
}
|
|
|
|
private abstract static class AbstractEnable implements Nonza {
|
|
|
|
/**
|
|
* Preferred maximum resumption time in seconds (optional).
|
|
*/
|
|
protected int max = -1;
|
|
|
|
protected boolean resume = false;
|
|
|
|
protected void maybeAddResumeAttributeTo(XmlStringBuilder xml) {
|
|
if (resume) {
|
|
// XEP 198 never mentions the case where resume='false', it's either set to true or
|
|
// not set at all. We reflect this in this code part
|
|
xml.attribute("resume", "true");
|
|
}
|
|
}
|
|
|
|
protected void maybeAddMaxAttributeTo(XmlStringBuilder xml) {
|
|
if (max > 0) {
|
|
xml.attribute("max", Integer.toString(max));
|
|
}
|
|
}
|
|
|
|
public boolean isResumeSet() {
|
|
return resume;
|
|
}
|
|
|
|
/**
|
|
* Return the max resumption time in seconds.
|
|
* @return the max resumption time in seconds
|
|
*/
|
|
public int getMaxResumptionTime() {
|
|
return max;
|
|
}
|
|
|
|
@Override
|
|
public final String getNamespace() {
|
|
return NAMESPACE;
|
|
}
|
|
}
|
|
|
|
public static class Enable extends AbstractEnable {
|
|
public static final String ELEMENT = "enable";
|
|
|
|
public static final Enable INSTANCE = new Enable();
|
|
|
|
private Enable() {
|
|
}
|
|
|
|
public Enable(boolean resume) {
|
|
this.resume = resume;
|
|
}
|
|
|
|
public Enable(boolean resume, int max) {
|
|
this(resume);
|
|
this.max = max;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
|
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
|
|
maybeAddResumeAttributeTo(xml);
|
|
maybeAddMaxAttributeTo(xml);
|
|
xml.closeEmptyElement();
|
|
return xml;
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A Stream Management 'enabled' element.
|
|
* <p>
|
|
* Here is a full example, all attributes besides 'xmlns' are optional.
|
|
* </p>
|
|
* <pre>
|
|
* {@code
|
|
* <enabled xmlns='urn:xmpp:sm:3'
|
|
* id='some-long-sm-id'
|
|
* location='[2001:41D0:1:A49b::1]:9222'
|
|
* resume='true'/>
|
|
* }
|
|
* </pre>
|
|
*/
|
|
public static class Enabled extends AbstractEnable {
|
|
public static final String ELEMENT = "enabled";
|
|
|
|
/**
|
|
* The stream id ("SM-ID")
|
|
*/
|
|
private final String id;
|
|
|
|
/**
|
|
* The location where the server prefers reconnection.
|
|
*/
|
|
private final String location;
|
|
|
|
public Enabled(String id, boolean resume) {
|
|
this(id, resume, null, -1);
|
|
}
|
|
|
|
public Enabled(String id, boolean resume, String location, int max) {
|
|
this.id = id;
|
|
this.resume = resume;
|
|
this.location = location;
|
|
this.max = max;
|
|
}
|
|
|
|
public String getId() {
|
|
return id;
|
|
}
|
|
|
|
public String getLocation() {
|
|
return location;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
|
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
|
|
xml.optAttribute("id", id);
|
|
maybeAddResumeAttributeTo(xml);
|
|
xml.optAttribute("location", location);
|
|
maybeAddMaxAttributeTo(xml);
|
|
xml.closeEmptyElement();
|
|
return xml;
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
}
|
|
|
|
public static class Failed implements Nonza {
|
|
public static final String ELEMENT = "failed";
|
|
|
|
private final StanzaError.Condition condition;
|
|
|
|
private final List<StanzaErrorTextElement> textElements;
|
|
|
|
|
|
public Failed() {
|
|
this(null, null);
|
|
}
|
|
|
|
public Failed(StanzaError.Condition condition, List<StanzaErrorTextElement> textElements) {
|
|
this.condition = condition;
|
|
if (textElements == null) {
|
|
this.textElements = Collections.emptyList();
|
|
} else {
|
|
this.textElements = Collections.unmodifiableList(textElements);
|
|
}
|
|
}
|
|
|
|
public StanzaError.Condition getStanzaErrorCondition() {
|
|
return condition;
|
|
}
|
|
|
|
public List<StanzaErrorTextElement> getTextElements() {
|
|
return textElements;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
|
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
|
|
if (condition == null && textElements.isEmpty()) {
|
|
xml.closeEmptyElement();
|
|
} else {
|
|
if (condition != null) {
|
|
xml.rightAngleBracket();
|
|
xml.append(condition.toString());
|
|
xml.xmlnsAttribute(StanzaError.ERROR_CONDITION_AND_TEXT_NAMESPACE);
|
|
xml.closeEmptyElement();
|
|
}
|
|
xml.append(textElements);
|
|
xml.closeElement(ELEMENT);
|
|
}
|
|
return xml;
|
|
}
|
|
|
|
@Override
|
|
public String getNamespace() {
|
|
return NAMESPACE;
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
|
|
}
|
|
|
|
private abstract static class AbstractResume implements Nonza {
|
|
|
|
private final long handledCount;
|
|
private final String previd;
|
|
|
|
private AbstractResume(long handledCount, String previd) {
|
|
this.handledCount = handledCount;
|
|
this.previd = previd;
|
|
}
|
|
|
|
public long getHandledCount() {
|
|
return handledCount;
|
|
}
|
|
|
|
public String getPrevId() {
|
|
return previd;
|
|
}
|
|
|
|
@Override
|
|
public final String getNamespace() {
|
|
return NAMESPACE;
|
|
}
|
|
|
|
@Override
|
|
public final XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
|
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
|
|
xml.attribute("h", Long.toString(handledCount));
|
|
xml.attribute("previd", previd);
|
|
xml.closeEmptyElement();
|
|
return xml;
|
|
}
|
|
}
|
|
|
|
public static class Resume extends AbstractResume {
|
|
public static final String ELEMENT = "resume";
|
|
|
|
public Resume(long handledCount, String previd) {
|
|
super(handledCount, previd);
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
}
|
|
|
|
public static class Resumed extends AbstractResume {
|
|
public static final String ELEMENT = "resumed";
|
|
|
|
public Resumed(long handledCount, String previd) {
|
|
super(handledCount, previd);
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
}
|
|
|
|
public static class AckAnswer implements Nonza {
|
|
public static final String ELEMENT = "a";
|
|
|
|
private final long handledCount;
|
|
|
|
public AckAnswer(long handledCount) {
|
|
this.handledCount = handledCount;
|
|
}
|
|
|
|
public long getHandledCount() {
|
|
return handledCount;
|
|
}
|
|
|
|
@Override
|
|
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
|
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingNamespace);
|
|
xml.attribute("h", Long.toString(handledCount));
|
|
xml.closeEmptyElement();
|
|
return xml;
|
|
}
|
|
|
|
@Override
|
|
public String getNamespace() {
|
|
return NAMESPACE;
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
}
|
|
|
|
public static final class AckRequest implements Nonza {
|
|
public static final String ELEMENT = "r";
|
|
public static final AckRequest INSTANCE = new AckRequest();
|
|
|
|
private AckRequest() {
|
|
}
|
|
|
|
@Override
|
|
public CharSequence toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
|
|
return '<' + ELEMENT + " xmlns='" + NAMESPACE + "'/>";
|
|
}
|
|
|
|
@Override
|
|
public String getNamespace() {
|
|
return NAMESPACE;
|
|
}
|
|
|
|
@Override
|
|
public String getElementName() {
|
|
return ELEMENT;
|
|
}
|
|
}
|
|
}
|