diff --git a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java index 6071b5586..e1ccba93e 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/util/PacketParserUtils.java @@ -63,8 +63,7 @@ public class PacketParserUtils { } public static XmlPullParser getParserFor(Reader reader) throws XmlPullParserException, IOException { - XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + XmlPullParser parser = newXmppParser(); parser.setInput(reader); // Wind the parser forward to the first start tag diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java index 833c33637..13cf6472d 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/XHTMLManager.java @@ -54,7 +54,7 @@ public class XHTMLManager { * @param message an XHTML message * @return an Iterator for the bodies in the message or null if none. */ - public static List getBodies(Message message) { + public static List getBodies(Message message) { XHTMLExtension xhtmlExtension = (XHTMLExtension) message.getExtension(XHTMLExtension.ELEMENT, XHTMLExtension.NAMESPACE); if (xhtmlExtension != null) return xhtmlExtension.getBodies(); diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java index f91f32b07..5325ab3de 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/packet/XHTMLExtension.java @@ -26,14 +26,11 @@ import java.util.List; /** * 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.

- * + * extension is only a subset of XHTML 1.0. + *

* The following link summarizes the requirements of XHTML IM: - * Valid tags.

- * - * Warning: this is an non-standard protocol documented by - * XEP-71. Because this is a - * non-standard protocol, it is subject to change. + * XEP-0071: XHTML-IM. + *

* * @author Gaston Dombiak */ @@ -42,7 +39,7 @@ public class XHTMLExtension implements PacketExtension { public static final String ELEMENT = "html"; public static final String NAMESPACE = "http://jabber.org/protocol/xhtml-im"; - private List bodies = new ArrayList(); + private List bodies = new ArrayList(); /** * 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); xml.rightAngelBracket(); // Loop through all the bodies and append them to the string buffer - for (String body : getBodies()) { + for (CharSequence body : getBodies()) { xml.append(body); } xml.closeElement(this); @@ -97,9 +94,9 @@ public class XHTMLExtension implements PacketExtension { * * @return a List of the bodies in the packet. */ - public List getBodies() { + public List getBodies() { synchronized (bodies) { - return Collections.unmodifiableList(new ArrayList(bodies)); + return Collections.unmodifiableList(new ArrayList(bodies)); } } @@ -108,7 +105,7 @@ public class XHTMLExtension implements PacketExtension { * * @param body the body to add. */ - public void addBody(String body) { + public void addBody(CharSequence body) { synchronized (bodies) { bodies.add(body); } @@ -120,7 +117,9 @@ public class XHTMLExtension implements PacketExtension { * @return the number of bodies in the XHTML packet. */ public int getBodiesCount() { - return bodies.size(); + synchronized (bodies) { + return bodies.size(); + } } } diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProvider.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProvider.java index 16e280374..a424b6b14 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProvider.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProvider.java @@ -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"); * 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.PacketExtension; 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.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -29,108 +29,27 @@ import java.io.IOException; /** * The XHTMLExtensionProvider parses XHTML packets. * - * @author Vyacheslav Blinov + * @author Florian Schmaus */ public class XHTMLExtensionProvider implements PacketExtensionProvider { @Override public PacketExtension parseExtension(XmlPullParser parser) throws IOException, XmlPullParserException { XHTMLExtension xhtmlExtension = new XHTMLExtension(); - final String XHTML_EXTENSION_ELEMENT_NAME = xhtmlExtension.getElementName(); int startDepth = parser.getDepth(); - int tagDepth = parser.getDepth(); - boolean tagStarted = false; - StringBuilder buffer = new StringBuilder(); - while (true) { - int eventType = parser.next(); + int eventType = parser.getEventType(); + String name = parser.getName(); if (eventType == XmlPullParser.START_TAG) { - boolean appendNamespace = false; - if (Message.BODY.equals(parser.getName())) { - buffer = new StringBuilder(); - tagDepth = parser.getDepth(); - appendNamespace = true; + if (name.equals(Message.BODY)) { + xhtmlExtension.addBody(PacketParserUtils.parseElement(parser)); } - 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) { - String name = parser.getName(); - if (XHTML_EXTENSION_ELEMENT_NAME.equals(name) && parser.getDepth() <= startDepth) { + if (name.equals(XHTMLExtension.ELEMENT) && parser.getDepth() <= startDepth) { 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("'); - } - } - - 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; - } } diff --git a/smack-extensions/src/test/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProviderTest.java b/smack-extensions/src/test/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProviderTest.java index 31227808c..bcb741697 100644 --- a/smack-extensions/src/test/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProviderTest.java +++ b/smack-extensions/src/test/java/org/jivesoftware/smackx/xhtmlim/provider/XHTMLExtensionProviderTest.java @@ -17,11 +17,11 @@ package org.jivesoftware.smackx.xhtmlim.provider; import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.util.PacketParserUtils; import org.jivesoftware.smackx.xhtmlim.packet.XHTMLExtension; import org.junit.Test; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; import java.io.IOException; @@ -36,8 +36,7 @@ public class XHTMLExtensionProviderTest { @Test public void parsesWell() throws IOException, XmlPullParserException { - XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); + XmlPullParser parser = PacketParserUtils.newXmppParser(); parser.setInput(getClass().getResourceAsStream(XHTML_EXTENSION_SAMPLE_RESOURCE_NAME), "UTF-8"); parser.next();