1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-16 08:34:50 +02:00
Smack/smack-streammanagement/src/main/java/org/jivesoftware/smack/sm/packet/StreamManagement.java
Florian Schmaus 3d4e7938a7 Make ExtensionElement marker interface wrt. QNAME field
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).
2021-04-18 21:07:19 +02:00

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;
}
}
}