Improve SHIM API

- HeadersExtension.getHeaders() now returns a List instead of a
  Collection
- Use XmlStringBuilder in Header and HeadersExtension toXML()
- Add HeadersProviderTest
- Use Smack formatting

Also remove duplicate parsing code regarding SHIM from HOXT
implementation.
This commit is contained in:
Florian Schmaus 2015-01-01 23:57:44 +01:00
parent 06add179ec
commit f2703bc195
7 changed files with 164 additions and 123 deletions

View File

@ -16,6 +16,8 @@
*/
package org.jivesoftware.smack.util;
import java.util.Collection;
import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.PacketExtension;
@ -272,6 +274,13 @@ public class XmlStringBuilder implements Appendable, CharSequence {
return this;
}
public XmlStringBuilder append(Collection<? extends Element> elements) {
for (Element element : elements) {
append(element.toXML());
}
return this;
}
public XmlStringBuilder emptyElement(Enum<?> element) {
return emptyElement(element.name());
}

View File

@ -21,15 +21,12 @@ import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.hoxt.packet.AbstractHttpOverXmpp;
import org.jivesoftware.smackx.shim.packet.Header;
import org.jivesoftware.smackx.shim.packet.HeadersExtension;
import org.jivesoftware.smackx.shim.provider.HeaderProvider;
import org.jivesoftware.smackx.shim.provider.HeadersProvider;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* Abstract parent for Req and Resp packet providers.
@ -39,8 +36,6 @@ import java.util.Set;
*/
public abstract class AbstractHttpOverXmppProvider<H extends AbstractHttpOverXmpp> extends IQProvider<H> {
private static final String ELEMENT_HEADERS = "headers";
private static final String ELEMENT_HEADER = "header";
private static final String ELEMENT_DATA = "data";
private static final String ELEMENT_TEXT = "text";
private static final String ELEMENT_BASE_64 = "base64";
@ -71,8 +66,8 @@ public abstract class AbstractHttpOverXmppProvider<H extends AbstractHttpOverXmp
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals(ELEMENT_HEADERS)) {
HeadersExtension headersExtension = parseHeaders(parser);
if (parser.getName().equals(HeadersExtension.ELEMENT)) {
HeadersExtension headersExtension = HeadersProvider.INSTANCE.parse(parser);
body.setHeaders(headersExtension);
} else if (parser.getName().endsWith(ELEMENT_DATA)) {
AbstractHttpOverXmpp.Data data = parseData(parser);
@ -88,28 +83,6 @@ public abstract class AbstractHttpOverXmppProvider<H extends AbstractHttpOverXmp
}
}
private HeadersExtension parseHeaders(XmlPullParser parser) throws XmlPullParserException, IOException, SmackException {
HeaderProvider provider = new HeaderProvider();
Set<Header> set = new HashSet<Header>();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals(ELEMENT_HEADER)) {
Header header = provider.parse(parser);
set.add(header);
}
} else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_HEADERS)) {
done = true;
}
}
}
return new HeadersExtension(set);
}
private AbstractHttpOverXmpp.Data parseData(XmlPullParser parser) throws XmlPullParserException, IOException {
NamedElement child = null;
boolean done = false;

View File

@ -16,47 +16,50 @@
*/
package org.jivesoftware.smackx.shim.packet;
import org.jivesoftware.smack.packet.NamedElement;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.XmlStringBuilder;
/**
* Represents a <b>Header</b> entry as specified by the <a href="http://xmpp.org/extensions/xep-031.html">Stanza Headers and Internet Metadata (SHIM)</a>
* @author Robin Collier
*/
public class Header implements PacketExtension
{
private String name;
private String value;
public Header(String name, String value)
{
this.name = name;
this.value = value;
}
public String getName()
{
return name;
}
public class Header implements PacketExtension {
public static final String ELEMENT = "header";
public String getValue()
{
return value;
}
private final String name;
private final String value;
public String getElementName()
{
return "header";
}
public Header(String name, String value) {
this.name = name;
this.value = value;
}
public String getNamespace()
{
return HeadersExtension.NAMESPACE;
}
public String getName() {
return name;
}
public String toXML()
{
return "<header name='" + name + "'>" + value + "</header>";
}
public String getValue() {
return value;
}
public String getElementName() {
return ELEMENT;
}
public String getNamespace() {
return HeadersExtension.NAMESPACE;
}
@Override
public XmlStringBuilder toXML() {
// Upcast to NamedElement since we don't want a xmlns attribute
XmlStringBuilder xml = new XmlStringBuilder((NamedElement) this);
xml.attribute("name", name);
xml.rightAngleBracket();
xml.escape(value);
xml.closeElement(this);
return xml;
}
}

View File

@ -16,10 +16,12 @@
*/
package org.jivesoftware.smackx.shim.packet;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.XmlStringBuilder;
/**
* Extension representing a list of headers as specified in <a href="http://xmpp.org/extensions/xep-0131">Stanza Headers and Internet Metadata (SHIM)</a>
@ -28,44 +30,48 @@ import org.jivesoftware.smack.packet.PacketExtension;
*
* @author Robin Collier
*/
public class HeadersExtension implements PacketExtension
{
public static final String NAMESPACE = "http://jabber.org/protocol/shim";
private Collection<Header> headers = Collections.emptyList();
public HeadersExtension(Collection<Header> headerList)
{
if (headerList != null)
headers = headerList;
}
public Collection<Header> getHeaders()
{
return headers;
}
public class HeadersExtension implements PacketExtension {
public static final String ELEMENT = "headers";
public static final String NAMESPACE = "http://jabber.org/protocol/shim";
public String getElementName()
{
return "headers";
}
private final List<Header> headers;
public String getNamespace()
{
return NAMESPACE;
}
public HeadersExtension(List<Header> headerList) {
if (headerList != null) {
headers = Collections.unmodifiableList(headerList);
} else {
headers = Collections.emptyList();
}
}
public String toXML()
{
StringBuilder builder = new StringBuilder("<" + getElementName() + " xmlns='" + getNamespace() + "'>");
for (Header header : headers)
{
builder.append(header.toXML());
}
builder.append("</" + getElementName() + '>');
public List<Header> getHeaders() {
return headers;
}
return builder.toString();
}
public String getElementName() {
return ELEMENT;
}
public String getNamespace() {
return NAMESPACE;
}
@Override
public XmlStringBuilder toXML() {
XmlStringBuilder xml = new XmlStringBuilder(this);
xml.rightAngleBracket();
xml.append(headers);
xml.closeElement(this);
return xml;
}
/**
* Return the SHIM headers extension of this stanza or null if there is none.
*
* @param packet
* @return the headers extension or null.
*/
public static HeadersExtension from(Packet packet) {
return packet.getExtension(ELEMENT, NAMESPACE);
}
}

View File

@ -28,23 +28,23 @@ import org.xmlpull.v1.XmlPullParserException;
*
* @author Robin Collier
*/
public class HeaderProvider extends PacketExtensionProvider<Header>
{
public class HeaderProvider extends PacketExtensionProvider<Header> {
@Override
public Header parse(XmlPullParser parser, int initialDepth)
throws XmlPullParserException, IOException {
String name = parser.getAttributeValue(null, "name");
String value = null;
parser.next();
if (parser.getEventType() == XmlPullParser.TEXT)
value = parser.getText();
while(parser.getEventType() != XmlPullParser.END_TAG)
parser.next();
return new Header(name, value);
}
public Header parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException {
String name = parser.getAttributeValue(null, "name");
String value = null;
parser.next();
if (parser.getEventType() == XmlPullParser.TEXT) {
value = parser.getText();
}
while (parser.getEventType() != XmlPullParser.END_TAG) {
parser.next();
}
return new Header(name, value);
}
}

View File

@ -16,7 +16,6 @@
*/
package org.jivesoftware.smackx.shim.provider;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -30,13 +29,14 @@ import org.jivesoftware.smackx.shim.packet.HeadersExtension;
*
* @author Robin Collier
*/
public class HeadersProvider extends EmbeddedExtensionProvider<HeadersExtension>
{
@SuppressWarnings("unchecked")
@Override
protected HeadersExtension createReturnExtension(String currentElement, String currentNamespace, Map<String, String> attributeMap, List<? extends PacketExtension> content)
{
return new HeadersExtension((Collection<Header>)content);
}
public class HeadersProvider extends EmbeddedExtensionProvider<HeadersExtension> {
public static final HeadersProvider INSTANCE = new HeadersProvider();
@SuppressWarnings("unchecked")
@Override
protected HeadersExtension createReturnExtension(String currentElement, String currentNamespace,
Map<String, String> attributeMap, List<? extends PacketExtension> content) {
return new HeadersExtension((List<Header>) content);
}
}

View File

@ -0,0 +1,50 @@
/**
*
* Copyright 2014 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.smackx.shim.provider;
import static org.junit.Assert.assertEquals;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.test.util.TestUtils;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.shim.packet.Header;
import org.jivesoftware.smackx.shim.packet.HeadersExtension;
import org.junit.Test;
import org.xmlpull.v1.XmlPullParser;
public class HeadersProviderTest {
@Test
public void headersInMessageTest() throws Exception {
// @formatter:off
final String messageStanza =
"<message from='romeo@shakespeare.lit/orchard' to='juliet@capulet.com' type='chat'>" +
"<body>Wherefore are thou?!?</body>" +
"<headers xmlns='http://jabber.org/protocol/shim'>" +
"<header name='Urgency'>high</header>" +
"</headers>" +
"</message>";
// @formatter:on
XmlPullParser parser = TestUtils.getMessageParser(messageStanza);
Message message = PacketParserUtils.parseMessage(parser);
HeadersExtension headers = HeadersExtension.from(message);
Header header = headers.getHeaders().get(0);
assertEquals("Urgency", header.getName());
assertEquals("high", header.getValue());
}
}