1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-12-22 18:48:00 +01:00

[jingle] Improve Jingle <reason/> support

Fixes SMACK-922.
This commit is contained in:
Florian Schmaus 2022-01-29 23:09:06 +01:00
parent c06cf72337
commit 7fad14ac0c
3 changed files with 149 additions and 33 deletions

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2017-2019 Florian Schmaus
* Copyright 2017-2022 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,7 @@ package org.jivesoftware.smackx.jingle.element;
import java.util.HashMap;
import java.util.Map;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.FullyQualifiedElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.util.StringUtils;
@ -105,9 +106,17 @@ public class JingleReason implements FullyQualifiedElement {
}
protected final Reason reason;
private final String text;
private final ExtensionElement element;
public JingleReason(Reason reason) {
this(reason, null, null);
}
public JingleReason(Reason reason, String text, ExtensionElement element) {
this.reason = reason;
this.text = text;
this.element = element;
}
@Override
@ -120,6 +129,26 @@ public class JingleReason implements FullyQualifiedElement {
return NAMESPACE;
}
/**
* An optional text that provides human-readable information about the reason for the action.
*
* @return a human-readable text with information regarding this reason or <code>null</code>.
* @since 4.4.5
*/
public String getText() {
return text;
}
/**
* An optional element that provides more detailed machine-readable information about the reason for the action.
*
* @return an elemnet with machine-readable information about this reason or <code>null</code>.
* @since 4.4.5
*/
public ExtensionElement getElement() {
return element;
}
@Override
public XmlStringBuilder toXML(XmlEnvironment enclosingXmlEnvironment) {
XmlStringBuilder xml = new XmlStringBuilder(this, enclosingXmlEnvironment);
@ -142,7 +171,11 @@ public class JingleReason implements FullyQualifiedElement {
private final String sessionId;
public AlternativeSession(String sessionId) {
super(Reason.alternative_session);
this(sessionId, null, null);
}
public AlternativeSession(String sessionId, String text, ExtensionElement element) {
super(Reason.alternative_session, text, element);
if (StringUtils.isNullOrEmpty(sessionId)) {
throw new NullPointerException("SessionID must not be null or empty.");
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2017-2021 Florian Schmaus
* Copyright 2017-2022 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,12 +19,14 @@ package org.jivesoftware.smackx.jingle.provider;
import java.io.IOException;
import java.util.logging.Logger;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.IqData;
import org.jivesoftware.smack.packet.StandardExtensionElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.parsing.StandardExtensionElementProvider;
import org.jivesoftware.smack.provider.IqProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.util.ParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.xml.XmlPullParserException;
@ -76,16 +78,7 @@ public class JingleProvider extends IqProvider<Jingle> {
builder.addJingleContent(content);
break;
case JingleReason.ELEMENT:
parser.next();
String reasonString = parser.getName();
JingleReason reason;
if (reasonString.equals("alternative-session")) {
parser.next();
String sid = parser.nextText();
reason = new JingleReason.AlternativeSession(sid);
} else {
reason = new JingleReason(Reason.fromString(reasonString));
}
JingleReason reason = parseJingleReason(parser);
builder.setReason(reason);
break;
default:
@ -178,4 +171,57 @@ public class JingleProvider extends IqProvider<Jingle> {
return builder.build();
}
public static JingleReason parseJingleReason(XmlPullParser parser)
throws XmlPullParserException, IOException, SmackParsingException {
ParserUtils.assertAtStartTag(parser);
final int initialDepth = parser.getDepth();
final String jingleNamespace = parser.getNamespace();
JingleReason.Reason reason = null;
ExtensionElement element = null;
String text = null;
// 'sid' is only set if the reason is 'alternative-session'.
String sid = null;
outerloop: while (true) {
XmlPullParser.TagEvent event = parser.nextTag();
switch (event) {
case START_ELEMENT:
String elementName = parser.getName();
String namespace = parser.getNamespace();
if (namespace.equals(jingleNamespace)) {
switch (elementName) {
case "text":
text = parser.nextText();
break;
case "alternative-session":
parser.next();
sid = parser.nextText();
break;
default:
reason = Reason.fromString(elementName);
break;
}
} else {
element = PacketParserUtils.parseExtensionElement(elementName, namespace, parser, null);
}
break;
case END_ELEMENT:
if (parser.getDepth() == initialDepth) {
break outerloop;
}
break;
}
}
JingleReason res;
if (sid != null) {
res = new JingleReason.AlternativeSession(sid, text, element);
} else {
res = new JingleReason(reason, text, element);
}
return res;
}
}

View file

@ -1,6 +1,6 @@
/**
*
* Copyright 2017 Florian Schmaus
* Copyright 2017-2022 Florian Schmaus
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,23 +17,30 @@
package org.jivesoftware.smackx.jingle.provider;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smack.xml.XmlPullParser;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.StandardExtensionElement;
import org.jivesoftware.smack.parsing.SmackParsingException;
import org.jivesoftware.smack.test.util.SmackTestUtil;
import org.jivesoftware.smack.xml.XmlPullParserException;
import org.jivesoftware.smackx.jingle.element.Jingle;
import org.jivesoftware.smackx.jingle.element.JingleContentDescription;
import org.jivesoftware.smackx.jingle.element.JingleContentTransport;
import org.jivesoftware.smackx.jingle.element.JingleReason;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
public class JingleProviderTest {
@Test
public void testParseUnknownJingleContentDescrption() throws Exception {
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testParseUnknownJingleContentDescrption(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
final String unknownJingleContentDescriptionNamespace = "urn:xmpp:jingle:unknown-description:5";
final String unknownJingleContentDescription =
// @formatter:off
@ -50,8 +57,8 @@ public class JingleProviderTest {
"</file>" +
"</description>";
// @formatter:on
XmlPullParser parser = createTestJingle(unknownJingleContentDescription);
Jingle jingle = (Jingle) PacketParserUtils.parseIQ(parser);
CharSequence xml = createTestJingle(unknownJingleContentDescription);
Jingle jingle = SmackTestUtil.parse(xml, JingleProvider.class, parserKind);
JingleContentDescription jingleContentDescription = jingle.getSoleContentOrThrow().getDescription();
@ -59,8 +66,10 @@ public class JingleProviderTest {
assertEquals(unknownJingleContentDescriptionNamespace, parsedUnknownJingleContentDescriptionNamespace);
}
@Test
public void testParseUnknownJingleContentTransport() throws Exception {
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testParseUnknownJingleContentTransport(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
final String unknownJingleContentTransportNamespace = "urn:xmpp:jingle:unknown-transport:foo:1";
final String unknownJingleContentTransport =
// @formatter:off
@ -81,8 +90,8 @@ public class JingleProviderTest {
" type='direct'/>" +
"</transport>";
// @formatter:on
XmlPullParser parser = createTestJingle(unknownJingleContentTransport);
Jingle jingle = (Jingle) PacketParserUtils.parseIQ(parser);
CharSequence xml = createTestJingle(unknownJingleContentTransport);
Jingle jingle = SmackTestUtil.parse(xml, JingleProvider.class, parserKind);
JingleContentTransport jingleContentTransport = jingle.getSoleContentOrThrow().getTransport();
@ -90,7 +99,38 @@ public class JingleProviderTest {
assertEquals(unknownJingleContentTransportNamespace, parsedUnknownJingleContentTransportNamespace);
}
private static XmlPullParser createTestJingle(String... childs) throws XmlPullParserException, IOException {
@ParameterizedTest
@EnumSource(SmackTestUtil.XmlPullParserKind.class)
public void testReasonElementWithExtraElement(SmackTestUtil.XmlPullParserKind parserKind)
throws XmlPullParserException, IOException, SmackParsingException {
String xml = "<iq from='juliet@capulet.lit/balcony'"
+ " id='le71fa63'"
+ " to='romeo@montague.lit/orchard'"
+ " type='set'>"
+ "<jingle xmlns='urn:xmpp:jingle:1'"
+ " action='session-terminate'"
+ " sid='a73sjjvkla37jfea'>"
+ "<reason>"
+ "<success/>"
+ "<my-element xmlns='https://example.org' foo='bar'/>"
+ "</reason>"
+ "</jingle>"
+ "</iq>";
Jingle jingle = SmackTestUtil.parse(xml, JingleProvider.class, parserKind);
JingleReason jingleReason = jingle.getReason();
assertEquals(JingleReason.Reason.success, jingleReason.asEnum());
ExtensionElement element = jingleReason.getElement();
// TODO: Use JUnit 5.8's assertInstanceOf when possible
// assertInstanceOf(StandardExtesionElement.class, extraElement);
assertTrue(element instanceof StandardExtensionElement);
StandardExtensionElement extraElement = (StandardExtensionElement) element;
assertEquals("https://example.org", extraElement.getNamespace());
assertEquals("bar", extraElement.getAttributes().get("foo"));
}
private static CharSequence createTestJingle(String... childs) throws XmlPullParserException, IOException {
StringBuilder sb = new StringBuilder();
sb.append(// @formatter:off
"<iq from='romeo@montague.example/dr4hcr0st3lup4c'" +
@ -98,9 +138,9 @@ public class JingleProviderTest {
" to='juliet@capulet.example/yn0cl4bnw0yr3vym'" +
" type='set'>" +
"<jingle xmlns='urn:xmpp:jingle:1' " +
" action='session-initiate' " +
" initiator='romeo@montague.example/dr4hcr0st3lup4c' " +
" sid='851ba2'>" +
"action='session-initiate' " +
"initiator='romeo@montague.example/dr4hcr0st3lup4c' " +
"sid='851ba2'>" +
"<content creator='initiator' name='a-file-offer' senders='initiator'>"
// @formatter:on
);
@ -114,9 +154,6 @@ public class JingleProviderTest {
// @formatter:on
);
String jingleStanza = sb.toString();
XmlPullParser parser = PacketParserUtils.getParserFor(jingleStanza);
return parser;
return sb;
}
}