From 813219179fcd0f995795a4f42b0aec9152643faa Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Sat, 17 Jun 2017 11:43:49 +0200 Subject: [PATCH] Add support for elements in SM's element Also introduce AbstractTextElement and StanzaErrorTextElement. Fixes SMACK-760. --- .../smack/packet/AbstractTextElement.java | 56 +++++++++++++++++++ .../smack/packet/StanzaErrorTextElement.java | 32 +++++++++++ .../smack/sm/packet/StreamManagement.java | 38 ++++++++++--- .../sm/provider/ParseStreamManagement.java | 16 +++++- .../provider/ParseStreamManagementTest.java | 29 +++++++++- 5 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java create mode 100644 smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaErrorTextElement.java diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java new file mode 100644 index 000000000..91f9f4582 --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/AbstractTextElement.java @@ -0,0 +1,56 @@ +/** + * + * Copyright © 2017 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.packet; + +import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; + +public abstract class AbstractTextElement implements ExtensionElement { + + public static final String ELEMENT = "text"; + + private final String text; + private final String lang; + + protected AbstractTextElement(String text, String lang) { + this.text = StringUtils.requireNotNullOrEmpty(text, "Text must not be null or empty"); + this.lang = lang; + } + + @Override + public String getElementName() { + return ELEMENT; + } + + @Override + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.optXmlLangAttribute(lang); + xml.rightAngleBracket(); + xml.escape(text); + xml.closeElement(this); + return xml; + } + + public final String getText() { + return text; + } + + public final String getLang() { + return lang; + } +} diff --git a/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaErrorTextElement.java b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaErrorTextElement.java new file mode 100644 index 000000000..a593ffc9d --- /dev/null +++ b/smack-core/src/main/java/org/jivesoftware/smack/packet/StanzaErrorTextElement.java @@ -0,0 +1,32 @@ +/** + * + * Copyright © 2017 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.packet; + +public class StanzaErrorTextElement extends AbstractTextElement { + + public static final String NAMESPACE = XMPPError.NAMESPACE; + + public StanzaErrorTextElement(String text, String lang) { + super(text, lang); + } + + @Override + public String getNamespace() { + return NAMESPACE; + } + +} diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/sm/packet/StreamManagement.java b/smack-tcp/src/main/java/org/jivesoftware/smack/sm/packet/StreamManagement.java index fc7e75213..96980ef26 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/sm/packet/StreamManagement.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/sm/packet/StreamManagement.java @@ -16,8 +16,12 @@ */ 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.StanzaErrorTextElement; import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.util.XmlStringBuilder; @@ -189,30 +193,46 @@ public class StreamManagement { public static class Failed implements Nonza { public static final String ELEMENT = "failed"; - private XMPPError.Condition condition; + private final XMPPError.Condition condition; + + private final List textElements; + public Failed() { + this(null, null); } - public Failed(XMPPError.Condition condition) { + public Failed(XMPPError.Condition condition, List textElements) { this.condition = condition; + if (textElements == null) { + this.textElements = Collections.emptyList(); + } else { + this.textElements = Collections.unmodifiableList(textElements); + } } public XMPPError.Condition getXMPPErrorCondition() { return condition; } + public List getTextElements() { + return textElements; + } + @Override public CharSequence toXML() { XmlStringBuilder xml = new XmlStringBuilder(this); - if (condition != null) { - xml.rightAngleBracket(); - xml.append(condition.toString()); - xml.xmlnsAttribute(XMPPError.NAMESPACE); - xml.closeElement(ELEMENT); - } - else { + if (condition == null && textElements.isEmpty()) { xml.closeEmptyElement(); + } else { + xml.rightAngleBracket(); + if (condition != null) { + // TODO This should use StanzaError (formerly XMPPError) in Smack 4.3 (see SMACK-769) + xml.append(condition.toString()); + xml.xmlnsAttribute(XMPPError.NAMESPACE); + } + xml.append(textElements); + xml.closeElement(ELEMENT); } return xml; } diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/sm/provider/ParseStreamManagement.java b/smack-tcp/src/main/java/org/jivesoftware/smack/sm/provider/ParseStreamManagement.java index 27a34cbd6..bf832db3d 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/sm/provider/ParseStreamManagement.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/sm/provider/ParseStreamManagement.java @@ -17,7 +17,11 @@ package org.jivesoftware.smack.sm.provider; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import org.jivesoftware.smack.packet.AbstractTextElement; +import org.jivesoftware.smack.packet.StanzaErrorTextElement; import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.sm.packet.StreamManagement.AckAnswer; import org.jivesoftware.smack.sm.packet.StreamManagement.AckRequest; @@ -46,6 +50,7 @@ public class ParseStreamManagement { ParserUtils.assertAtStartTag(parser); String name; XMPPError.Condition condition = null; + List textElements = new ArrayList<>(4); outerloop: while (true) { int event = parser.next(); @@ -54,7 +59,14 @@ public class ParseStreamManagement { name = parser.getName(); String namespace = parser.getNamespace(); if (XMPPError.NAMESPACE.equals(namespace)) { - condition = XMPPError.Condition.fromString(name); + if (name.equals(AbstractTextElement.ELEMENT)) { + String lang = ParserUtils.getXmlLang(parser); + String text = parser.nextText(); + StanzaErrorTextElement stanzaErrorTextElement = new StanzaErrorTextElement(text, lang); + textElements.add(stanzaErrorTextElement); + } else { + condition = XMPPError.Condition.fromString(name); + } } break; case XmlPullParser.END_TAG: @@ -66,7 +78,7 @@ public class ParseStreamManagement { } } ParserUtils.assertAtEndTag(parser); - return new Failed(condition); + return new Failed(condition, textElements); } public static Resumed resumed(XmlPullParser parser) throws XmlPullParserException, IOException { diff --git a/smack-tcp/src/test/java/org/jivesoftware/smack/sm/provider/ParseStreamManagementTest.java b/smack-tcp/src/test/java/org/jivesoftware/smack/sm/provider/ParseStreamManagementTest.java index 072d02da7..845930ca1 100644 --- a/smack-tcp/src/test/java/org/jivesoftware/smack/sm/provider/ParseStreamManagementTest.java +++ b/smack-tcp/src/test/java/org/jivesoftware/smack/sm/provider/ParseStreamManagementTest.java @@ -1,6 +1,6 @@ /** * - * Copyright 2014 Vyacheslav Blinov + * Copyright 2014 Vyacheslav Blinov, 2017 Florian Schmaus * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,8 +26,10 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.util.List; import java.util.Properties; +import org.jivesoftware.smack.packet.StanzaErrorTextElement; import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.sm.packet.StreamManagement; import org.jivesoftware.smack.util.PacketParserUtils; @@ -104,6 +106,30 @@ public class ParseStreamManagementTest { assertTrue(failedPacket.getXMPPErrorCondition() == errorCondition); } + @Test + public void testParseFailedWithTExt() throws XmlPullParserException, IOException { + // @formatter:off + final String failedNonza = "" + + "" + + "" + + "Previous session timed out" + + "" + + ""; + // @formatter:on + XmlPullParser parser = PacketParserUtils.getParserFor(failedNonza); + + StreamManagement.Failed failed = ParseStreamManagement.failed(parser); + + assertEquals(XMPPError.Condition.item_not_found, failed.getXMPPErrorCondition()); + + List textElements = failed.getTextElements(); + assertEquals(1, textElements.size()); + + StanzaErrorTextElement textElement = textElements.get(0); + assertEquals("Previous session timed out", textElement.getText()); + assertEquals("en", textElement.getLang()); + } + @Test public void testParseResumed() throws Exception { long handledPackets = 42; @@ -139,7 +165,6 @@ public class ParseStreamManagementTest { assertThat(acknowledgementPacket.getHandledCount(), equalTo(handledPackets)); } - private static Properties initOutputProperties() { Properties properties = new Properties(); properties.put(javax.xml.transform.OutputKeys.OMIT_XML_DECLARATION, "yes");