/** * * Copyright © 2014-2018 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 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 StreamManagementFeature INSTANCE = new StreamManagementFeature(); private StreamManagementFeature() { } @Override public String getElementName() { return ELEMENT; } @Override public String getNamespace() { return NAMESPACE; } @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. *

* Here is a full example, all attributes besides 'xmlns' are optional. *

*
     * {@code
     * 
     * }
     * 
*/ 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 textElements; public Failed() { this(null, null); } public Failed(StanzaError.Condition condition, List 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 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; } } }