1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-26 08:12:05 +01:00

Make XHMTMLExtensionProvider use parseElement()

which makes the whole provider much simpler.

Also use CharSequence as Base for XHTML-IM bodies.
This commit is contained in:
Florian Schmaus 2014-07-05 15:04:35 +02:00
parent 94a16ba41e
commit 54b18e3575
5 changed files with 25 additions and 109 deletions

View file

@ -63,8 +63,7 @@ public class PacketParserUtils {
} }
public static XmlPullParser getParserFor(Reader reader) throws XmlPullParserException, IOException { public static XmlPullParser getParserFor(Reader reader) throws XmlPullParserException, IOException {
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); XmlPullParser parser = newXmppParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(reader); parser.setInput(reader);
// Wind the parser forward to the first start tag // Wind the parser forward to the first start tag

View file

@ -54,7 +54,7 @@ public class XHTMLManager {
* @param message an XHTML message * @param message an XHTML message
* @return an Iterator for the bodies in the message or null if none. * @return an Iterator for the bodies in the message or null if none.
*/ */
public static List<String> getBodies(Message message) { public static List<CharSequence> getBodies(Message message) {
XHTMLExtension xhtmlExtension = (XHTMLExtension) message.getExtension(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE); XHTMLExtension xhtmlExtension = (XHTMLExtension) message.getExtension(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE);
if (xhtmlExtension != null) if (xhtmlExtension != null)
return xhtmlExtension.getBodies(); return xhtmlExtension.getBodies();

View file

@ -26,14 +26,11 @@ import java.util.List;
/** /**
* An XHTML sub-packet, which is used by XMPP clients to exchange formatted text. The XHTML * An XHTML sub-packet, which is used by XMPP clients to exchange formatted text. The XHTML
* extension is only a subset of XHTML 1.0.<p> * extension is only a subset of XHTML 1.0.
* * <p>
* The following link summarizes the requirements of XHTML IM: * The following link summarizes the requirements of XHTML IM:
* <a href="http://www.xmpp.org/extensions/jep-0071.html#sect-id2598018">Valid tags</a>.<p> * <a href="http://www.xmpp.org/extensions/xep-0071.html">XEP-0071: XHTML-IM</a>.
* * </p>
* Warning: this is an non-standard protocol documented by
* <a href="http://www.xmpp.org/extensions/jep-0071.html">XEP-71</a>. Because this is a
* non-standard protocol, it is subject to change.
* *
* @author Gaston Dombiak * @author Gaston Dombiak
*/ */
@ -42,7 +39,7 @@ public class XHTMLExtension implements PacketExtension {
public static final String ELEMENT = "html"; public static final String ELEMENT = "html";
public static final String NAMESPACE = "http://jabber.org/protocol/xhtml-im"; public static final String NAMESPACE = "http://jabber.org/protocol/xhtml-im";
private List<String> bodies = new ArrayList<String>(); private List<CharSequence> bodies = new ArrayList<CharSequence>();
/** /**
* Returns the XML element name of the extension sub-packet root element. * Returns the XML element name of the extension sub-packet root element.
@ -85,7 +82,7 @@ public class XHTMLExtension implements PacketExtension {
XmlStringBuilder xml = new XmlStringBuilder(this); XmlStringBuilder xml = new XmlStringBuilder(this);
xml.rightAngelBracket(); xml.rightAngelBracket();
// Loop through all the bodies and append them to the string buffer // Loop through all the bodies and append them to the string buffer
for (String body : getBodies()) { for (CharSequence body : getBodies()) {
xml.append(body); xml.append(body);
} }
xml.closeElement(this); xml.closeElement(this);
@ -97,9 +94,9 @@ public class XHTMLExtension implements PacketExtension {
* *
* @return a List of the bodies in the packet. * @return a List of the bodies in the packet.
*/ */
public List<String> getBodies() { public List<CharSequence> getBodies() {
synchronized (bodies) { synchronized (bodies) {
return Collections.unmodifiableList(new ArrayList<String>(bodies)); return Collections.unmodifiableList(new ArrayList<CharSequence>(bodies));
} }
} }
@ -108,7 +105,7 @@ public class XHTMLExtension implements PacketExtension {
* *
* @param body the body to add. * @param body the body to add.
*/ */
public void addBody(String body) { public void addBody(CharSequence body) {
synchronized (bodies) { synchronized (bodies) {
bodies.add(body); bodies.add(body);
} }
@ -120,7 +117,9 @@ public class XHTMLExtension implements PacketExtension {
* @return the number of bodies in the XHTML packet. * @return the number of bodies in the XHTML packet.
*/ */
public int getBodiesCount() { public int getBodiesCount() {
return bodies.size(); synchronized (bodies) {
return bodies.size();
}
} }
} }

View file

@ -1,6 +1,6 @@
/** /**
* *
* Copyright 2003-2007 Jive Software, 2014 Vyacheslav Blinov * Copyright 2003-2007 Jive Software, 2014 Florian Schmaus
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,7 @@ package org.jivesoftware.smackx.xhtmlim.provider;
import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider; import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension; import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
@ -29,108 +29,27 @@ import java.io.IOException;
/** /**
* The XHTMLExtensionProvider parses XHTML packets. * The XHTMLExtensionProvider parses XHTML packets.
* *
* @author Vyacheslav Blinov * @author Florian Schmaus
*/ */
public class XHTMLExtensionProvider implements PacketExtensionProvider { public class XHTMLExtensionProvider implements PacketExtensionProvider {
@Override @Override
public PacketExtension parseExtension(XmlPullParser parser) throws IOException, XmlPullParserException { public PacketExtension parseExtension(XmlPullParser parser) throws IOException, XmlPullParserException {
XHTMLExtension xhtmlExtension = new XHTMLExtension(); XHTMLExtension xhtmlExtension = new XHTMLExtension();
final String XHTML_EXTENSION_ELEMENT_NAME = xhtmlExtension.getElementName();
int startDepth = parser.getDepth(); int startDepth = parser.getDepth();
int tagDepth = parser.getDepth();
boolean tagStarted = false;
StringBuilder buffer = new StringBuilder();
while (true) { while (true) {
int eventType = parser.next(); int eventType = parser.getEventType();
String name = parser.getName();
if (eventType == XmlPullParser.START_TAG) { if (eventType == XmlPullParser.START_TAG) {
boolean appendNamespace = false; if (name.equals(Message.BODY)) {
if (Message.BODY.equals(parser.getName())) { xhtmlExtension.addBody(PacketParserUtils.parseElement(parser));
buffer = new StringBuilder();
tagDepth = parser.getDepth();
appendNamespace = true;
} }
maybeCloseTag(tagStarted, buffer);
appendStartTagPartial(buffer, parser, appendNamespace);
tagStarted = true;
} else if (eventType == XmlPullParser.TEXT) {
tagStarted = maybeCloseTag(tagStarted, buffer);
appendText(buffer, parser);
} else if (eventType == XmlPullParser.END_TAG) { } else if (eventType == XmlPullParser.END_TAG) {
String name = parser.getName(); if (name.equals(XHTMLExtension.ELEMENT) && parser.getDepth() <= startDepth) {
if (XHTML_EXTENSION_ELEMENT_NAME.equals(name) && parser.getDepth() <= startDepth) {
return xhtmlExtension; return xhtmlExtension;
} else {
// xpp does not allows us to detect if tag is self-closing, so we have to
// handle self-closing tags by our own means
appendEndTag(buffer, parser, tagStarted);
tagStarted = false;
if (Message.BODY.equals(name) && parser.getDepth() <= tagDepth) {
xhtmlExtension.addBody(buffer.toString());
}
} }
} }
parser.next();
} }
} }
private static void appendStartTagPartial(StringBuilder builder, XmlPullParser parser, boolean withNamespace) {
builder.append('<');
String prefix = parser.getPrefix();
if (StringUtils.isNotEmpty(prefix)) {
builder.append(prefix).append(':');
}
builder.append(parser.getName());
int attributesCount = parser.getAttributeCount();
// handle namespace
if (withNamespace) {
String namespace = parser.getNamespace();
if (StringUtils.isNotEmpty(namespace)) {
builder.append(" xmlns='").append(namespace).append('\'');
}
}
// handle attributes
for (int i = 0; i < attributesCount; ++i) {
builder.append(' ');
String attributeNamespace = parser.getAttributeNamespace(i);
if (StringUtils.isNotEmpty(attributeNamespace)) {
builder.append(attributeNamespace).append(':');
}
builder.append(parser.getAttributeName(i));
String value = parser.getAttributeValue(i);
if (value != null) {
// We need to return valid XML so any inner text needs to be re-escaped
builder.append("='").append(StringUtils.escapeForXML(value)).append('\'');
}
}
}
private static void appendEndTag(StringBuilder builder, XmlPullParser parser, boolean tagStarted) {
if (tagStarted) {
builder.append("/>");
} else {
builder.append("</").append(parser.getName()).append('>');
}
}
private static boolean appendText(StringBuilder builder, XmlPullParser parser) {
String text = parser.getText();
if (text == null) {
return false;
} else {
// We need to return valid XML so any inner text needs to be re-escaped
builder.append(StringUtils.escapeForXML(parser.getText()));
return true;
}
}
private static boolean maybeCloseTag(boolean tagStarted, StringBuilder builder) {
if (tagStarted) {
builder.append('>');
}
return false;
}
} }

View file

@ -17,11 +17,11 @@
package org.jivesoftware.smackx.xhtmlim.provider; package org.jivesoftware.smackx.xhtmlim.provider;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension; import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension;
import org.junit.Test; import org.junit.Test;
import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException; import java.io.IOException;
@ -36,8 +36,7 @@ public class XHTMLExtensionProviderTest {
@Test @Test
public void parsesWell() throws IOException, XmlPullParserException { public void parsesWell() throws IOException, XmlPullParserException {
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); XmlPullParser parser = PacketParserUtils.newXmppParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(getClass().getResourceAsStream(XHTML_EXTENSION_SAMPLE_RESOURCE_NAME), "UTF-8"); parser.setInput(getClass().getResourceAsStream(XHTML_EXTENSION_SAMPLE_RESOURCE_NAME), "UTF-8");
parser.next(); parser.next();