From 978f692eb0c35af9fc786e9b4d35363571f7d987 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Fri, 21 Mar 2014 09:51:52 +0100 Subject: [PATCH] Use XmlStringBuilder in most toXML() bodies Also change StringUtils.escapeForXML() and Packet.toXML() to return CharSequence instead of String. XmlStringBuilder now has 'optX' methods. Remove XmlUtils in favor of XmlStringBuilder --- .../jivesoftware/smack/BOSHConnection.java | 4 +- .../smack/DirectoryRosterStore.java | 6 +- .../smack/debugger/LiteDebugger.java | 4 +- .../org/jivesoftware/smack/packet/Bind.java | 24 ++-- .../smack/packet/DefaultPacketExtension.java | 17 +-- .../org/jivesoftware/smack/packet/IQ.java | 38 +++---- .../jivesoftware/smack/packet/Message.java | 56 ++++----- .../org/jivesoftware/smack/packet/Packet.java | 72 ++++++++---- .../smack/packet/PacketExtension.java | 2 +- .../jivesoftware/smack/packet/Presence.java | 48 +++----- .../smack/packet/Registration.java | 25 ++-- .../smack/packet/RosterPacket.java | 21 ++-- .../jivesoftware/smack/packet/Session.java | 3 +- .../jivesoftware/smack/packet/XMPPError.java | 2 +- .../smack/util/LazyStringBuilder.java | 89 +++++++++++++++ .../jivesoftware/smack/util/StringUtils.java | 4 +- .../smack/util/XmlStringBuilder.java | 107 +++++++++++++++--- .../org/jivesoftware/smack/util/XmlUtils.java | 34 ------ .../smack/packet/MessageTest.java | 14 +-- .../smack/packet/PresenceTest.java | 14 +-- .../smack/util/PacketParserUtilsTest.java | 64 +++++------ .../smack/util/StringUtilsTest.java | 26 +++-- .../smackx/debugger/EnhancedDebugger.java | 4 +- .../address/MultipleRecipientManager.java | 7 +- .../cache/SimpleDirectoryPersistentCache.java | 2 +- .../smackx/caps/packet/CapsExtension.java | 11 +- .../smackx/disco/packet/DiscoverInfo.java | 63 +++++------ .../smackx/disco/packet/DiscoverItems.java | 47 ++++---- .../smackx/pubsub/AffiliationsExtension.java | 2 +- .../jivesoftware/smackx/pubsub/FormNode.java | 2 +- .../smackx/pubsub/ItemsExtension.java | 2 +- .../smackx/pubsub/NodeExtension.java | 2 +- .../smackx/pubsub/OptionsExtension.java | 29 ++--- .../smackx/pubsub/SubscriptionsExtension.java | 2 +- .../smackx/pubsub/UnsubscribeExtension.java | 29 ++--- .../smackx/vcardtemp/packet/VCard.java | 4 +- .../jivesoftware/smackx/xdata/FormField.java | 9 +- .../bytestreams/ibb/packet/CloseTest.java | 2 +- .../bytestreams/ibb/packet/DataTest.java | 2 +- .../bytestreams/ibb/packet/OpenTest.java | 2 +- .../smackx/caps/EntityCapsManagerTest.java | 2 +- .../FileTransferNegotiatorTest.java | 3 +- .../java/org/jivesoftware/util/Protocol.java | 4 +- .../smackx/workgroup/agent/AgentSession.java | 3 - .../smackx/workgroup/ext/notes/ChatNotes.java | 5 +- .../smackx/workgroup/user/Workgroup.java | 7 +- .../org/jivesoftware/smack/PacketWriter.java | 4 +- 47 files changed, 511 insertions(+), 412 deletions(-) create mode 100644 core/src/main/java/org/jivesoftware/smack/util/LazyStringBuilder.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/XmlUtils.java diff --git a/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java b/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java index 382262e6c..4e9bf6288 100644 --- a/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java +++ b/bosh/src/main/java/org/jivesoftware/smack/BOSHConnection.java @@ -338,7 +338,7 @@ public class BOSHConnection extends XMPPConnection { void sendPacketInternal(Packet packet) { if (!done) { try { - send(ComposableBody.builder().setPayloadXML(packet.toXML()) + send(ComposableBody.builder().setPayloadXML(packet.toXML().toString()) .build()); } catch (BOSHException e) { LOGGER.log(Level.SEVERE, "BOSHException in sendPacketInternal", e); @@ -391,7 +391,7 @@ public class BOSHConnection extends XMPPConnection { try { client.disconnect(ComposableBody.builder() .setNamespaceDefinition("xmpp", XMPP_BOSH_NS) - .setPayloadXML(unavailablePresence.toXML()) + .setPayloadXML(unavailablePresence.toXML().toString()) .build()); // Wait 150 ms for processes to clean-up, then shutdown. Thread.sleep(150); diff --git a/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java b/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java index 38065bf8e..4d65e787f 100644 --- a/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java +++ b/core/src/main/java/org/jivesoftware/smack/DirectoryRosterStore.java @@ -291,9 +291,9 @@ public class DirectoryRosterStore implements RosterStore { XmlStringBuilder xml = new XmlStringBuilder(); xml.openElement("item"); xml.element("user", item.getUser()); - xml.element("name", item.getName()); - xml.element("type", item.getItemType()); - xml.element("status", item.getItemStatus()); + xml.optElement("name", item.getName()); + xml.optElement("type", item.getItemType()); + xml.optElement("status", item.getItemStatus()); for (String groupName : item.getGroupNames()) { xml.openElement("group"); xml.element("groupName", groupName); diff --git a/core/src/main/java/org/jivesoftware/smack/debugger/LiteDebugger.java b/core/src/main/java/org/jivesoftware/smack/debugger/LiteDebugger.java index 392dca30e..e73db8a01 100644 --- a/core/src/main/java/org/jivesoftware/smack/debugger/LiteDebugger.java +++ b/core/src/main/java/org/jivesoftware/smack/debugger/LiteDebugger.java @@ -241,8 +241,8 @@ public class LiteDebugger implements SmackDebugger { // data as Smack sees it and not as it's coming in as raw XML. listener = new PacketListener() { public void processPacket(Packet packet) { - interpretedText1.append(packet.toXML()); - interpretedText2.append(packet.toXML()); + interpretedText1.append(packet.toXML().toString()); + interpretedText2.append(packet.toXML().toString()); interpretedText1.append(NEWLINE); interpretedText2.append(NEWLINE); } diff --git a/core/src/main/java/org/jivesoftware/smack/packet/Bind.java b/core/src/main/java/org/jivesoftware/smack/packet/Bind.java index a90afb516..595178d64 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/Bind.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/Bind.java @@ -17,6 +17,8 @@ package org.jivesoftware.smack.packet; +import org.jivesoftware.smack.util.XmlStringBuilder; + /** * IQ packet used by Smack to bind a resource and to obtain the jid assigned by the server. * There are two ways to bind a resource. One is simply sending an empty Bind packet where the @@ -53,16 +55,16 @@ public class Bind extends IQ { this.jid = jid; } - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - if (resource != null) { - buf.append("").append(resource).append(""); - } - if (jid != null) { - buf.append("").append(jid).append(""); - } - buf.append(""); - return buf.toString(); + @Override + public CharSequence getChildElementXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement("bind"); + xml.xmlnsAttribute("urn:ietf:params:xml:ns:xmpp-bind"); + xml.rightAngelBracket(); + xml.optElement("resource", resource); + xml.optElement("jid", jid); + xml.closeElement("bind"); + + return xml; } } diff --git a/core/src/main/java/org/jivesoftware/smack/packet/DefaultPacketExtension.java b/core/src/main/java/org/jivesoftware/smack/packet/DefaultPacketExtension.java index e238ae1ed..1e7978564 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/DefaultPacketExtension.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/DefaultPacketExtension.java @@ -19,6 +19,8 @@ package org.jivesoftware.smack.packet; import java.util.*; +import org.jivesoftware.smack.util.XmlStringBuilder; + /** * Default implementation of the PacketExtension interface. Unless a PacketExtensionProvider * is registered with {@link org.jivesoftware.smack.provider.ProviderManager ProviderManager}, @@ -76,17 +78,16 @@ public class DefaultPacketExtension implements PacketExtension { return namespace; } - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append("<").append(elementName).append(" xmlns=\"").append(namespace).append("\">"); + @Override + public CharSequence toXML() { + XmlStringBuilder buf = new XmlStringBuilder(); + buf.halfOpenElement(elementName).xmlnsAttribute(namespace).rightAngelBracket(); for (String name : getNames()) { String value = getValue(name); - buf.append("<").append(name).append(">"); - buf.append(value); - buf.append(""); + buf.element(name, value); } - buf.append(""); - return buf.toString(); + buf.closeElement(elementName); + return buf; } /** diff --git a/core/src/main/java/org/jivesoftware/smack/packet/IQ.java b/core/src/main/java/org/jivesoftware/smack/packet/IQ.java index 0b0605850..5a62c851a 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/IQ.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/IQ.java @@ -17,7 +17,7 @@ package org.jivesoftware.smack.packet; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; /** * The base IQ (Info/Query) packet. IQ packets are used to get and set information @@ -71,36 +71,27 @@ public abstract class IQ extends Packet { } } - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); + buf.attribute("type", "get"); } else { - buf.append("type=\"").append(getType()).append("\">"); + buf.attribute("type", type.toString()); } + buf.rightAngelBracket(); // Add the query section if there is one. - String queryXML = getChildElementXML(); - if (queryXML != null) { - buf.append(queryXML); - } + buf.optAppend(getChildElementXML()); // Add the error sub-packet, if there is one. XMPPError error = getError(); if (error != null) { buf.append(error.toXML()); } - buf.append(""); - return buf.toString(); + buf.closeElement("iq"); + return buf; } /** @@ -111,7 +102,7 @@ public abstract class IQ extends Packet { * * @return the child element section of the IQ XML. */ - public abstract String getChildElementXML(); + public abstract CharSequence getChildElementXML(); /** * Convenience method to create a new empty {@link Type#RESULT IQ.Type.RESULT} @@ -170,7 +161,8 @@ public abstract class IQ extends Packet { "IQ must be of type 'set' or 'get'. Original IQ: " + request.toXML()); } final IQ result = new IQ() { - public String getChildElementXML() { + @Override + public CharSequence getChildElementXML() { return request.getChildElementXML(); } }; diff --git a/core/src/main/java/org/jivesoftware/smack/packet/Message.java b/core/src/main/java/org/jivesoftware/smack/packet/Message.java index 1a87eb2e3..102a12bcb 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/Message.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/Message.java @@ -17,7 +17,7 @@ package org.jivesoftware.smack.packet; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; import java.util.*; @@ -404,59 +404,47 @@ public class Message extends Packet { } - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); + buf.rightAngelBracket(); + // Add the subject in the default language Subject defaultSubject = getMessageSubject(null); if (defaultSubject != null) { - buf.append("").append(StringUtils.escapeForXML(defaultSubject.subject)).append(""); + buf.element("subject", defaultSubject.subject); } // Add the subject in other languages for (Subject subject : getSubjects()) { // Skip the default language if(subject.equals(defaultSubject)) continue; - buf.append(""); - buf.append(StringUtils.escapeForXML(subject.subject)); - buf.append(""); + buf.halfOpenElement("subject").xmllangAttribute(subject.language).rightAngelBracket(); + buf.escape(subject.subject); + buf.closeElement("subject"); } // Add the body in the default language Body defaultBody = getMessageBody(null); if (defaultBody != null) { - buf.append("").append(StringUtils.escapeForXML(defaultBody.message)).append(""); + buf.element("body", defaultBody.message); } // Add the bodies in other languages for (Body body : getBodies()) { // Skip the default language if(body.equals(defaultBody)) continue; - buf.append(""); - buf.append(StringUtils.escapeForXML(body.getMessage())); - buf.append(""); - } - if (thread != null) { - buf.append("").append(thread).append(""); + buf.halfOpenElement("body").xmllangAttribute(body.getLanguage()).rightAngelBracket(); + buf.escape(body.getMessage()); + buf.closeElement("body"); } + buf.optElement("thread", thread); // Append the error subpacket if the message type is an error. if (type == Type.error) { XMPPError error = getError(); @@ -466,8 +454,8 @@ public class Message extends Packet { } // Add packet extensions, if any are defined. buf.append(getExtensionsXML()); - buf.append(""); - return buf.toString(); + buf.closeElement("message"); + return buf; } diff --git a/core/src/main/java/org/jivesoftware/smack/packet/Packet.java b/core/src/main/java/org/jivesoftware/smack/packet/Packet.java index fab00a078..41024e2a8 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/Packet.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/Packet.java @@ -18,6 +18,7 @@ package org.jivesoftware.smack.packet; import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; @@ -352,7 +353,7 @@ public abstract class Packet { * * @return the XML format of the packet as a String. */ - public abstract String toXML(); + public abstract CharSequence toXML(); /** * Returns the extension sub-packets (including properties data) as an XML @@ -361,40 +362,47 @@ public abstract class Packet { * @return the extension sub-packets as XML or the Empty String if there * are no packet extensions. */ - protected synchronized String getExtensionsXML() { - StringBuilder buf = new StringBuilder(); + protected synchronized CharSequence getExtensionsXML() { + XmlStringBuilder xml = new XmlStringBuilder(); // Add in all standard extension sub-packets. for (PacketExtension extension : getExtensions()) { - buf.append(extension.toXML()); + xml.append(extension.toXML()); } // Add in packet properties. if (properties != null && !properties.isEmpty()) { - buf.append(""); + xml.halfOpenElement("properties").xmlnsAttribute("http://www.jivesoftware.com/xmlns/xmpp/properties"); // Loop through all properties and write them out. for (String name : getPropertyNames()) { Object value = getProperty(name); - buf.append(""); - buf.append("").append(StringUtils.escapeForXML(name)).append(""); - buf.append("").append(value).append(""); + type = "integer"; + valueStr = Integer.toString((Integer)value); } else if (value instanceof Long) { - buf.append("long\">").append(value).append(""); + type = "long"; + valueStr = Long.toString((Long) value); } else if (value instanceof Float) { - buf.append("float\">").append(value).append(""); + type = "float"; + valueStr = Float.toString((Float) value); } else if (value instanceof Double) { - buf.append("double\">").append(value).append(""); + type = "double"; + valueStr = Double.toString((Double) value); } else if (value instanceof Boolean) { - buf.append("boolean\">").append(value).append(""); + type = "boolean"; + valueStr = Boolean.toString((Boolean) value); } else if (value instanceof String) { - buf.append("string\">"); - buf.append(StringUtils.escapeForXML((String)value)); - buf.append(""); + type = "string"; + valueStr = (String) value; } // Otherwise, it's a generic Serializable object. Serialized objects are in // a binary format, which won't work well inside of XML. Therefore, we base-64 @@ -406,12 +414,13 @@ public abstract class Packet { byteStream = new ByteArrayOutputStream(); out = new ObjectOutputStream(byteStream); out.writeObject(value); - buf.append("java-object\">"); - String encodedVal = StringUtils.encodeBase64(byteStream.toByteArray()); - buf.append(encodedVal).append(""); + type ="java-object"; + valueStr = StringUtils.encodeBase64(byteStream.toByteArray()); } catch (Exception e) { LOGGER.log(Level.SEVERE, "Error encoding java object", e); + type ="java-object"; + valueStr = "Serializing error: " + e.getMessage(); } finally { if (out != null) { @@ -432,11 +441,15 @@ public abstract class Packet { } } } - buf.append(""); + xml.attribute("type", type); + xml.rightAngelBracket(); + xml.escape(valueStr); + xml.closeElement("value"); + xml.closeElement("property"); } - buf.append(""); + xml.closeElement("properties"); } - return buf.toString(); + return xml; } public String getXmlns() { @@ -485,9 +498,20 @@ public abstract class Packet { result = 31 * result + (error != null ? error.hashCode() : 0); return result; } - + @Override public String toString() { - return toXML(); + return toXML().toString(); + } + + /** + * Add to, from and id attributes + * + * @param xml + */ + protected void addCommonAttributes(XmlStringBuilder xml) { + xml.optAttribute("id", getPacketID()); + xml.optAttribute("to", getTo()); + xml.optAttribute("from", getFrom()); } } diff --git a/core/src/main/java/org/jivesoftware/smack/packet/PacketExtension.java b/core/src/main/java/org/jivesoftware/smack/packet/PacketExtension.java index 7e82d9358..3a20444e2 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/PacketExtension.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/PacketExtension.java @@ -49,5 +49,5 @@ public interface PacketExtension { * * @return the packet extension as XML. */ - public String toXML(); + public CharSequence toXML(); } diff --git a/core/src/main/java/org/jivesoftware/smack/packet/Presence.java b/core/src/main/java/org/jivesoftware/smack/packet/Presence.java index eb5d5fe6f..e264d0c8b 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/Presence.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/Presence.java @@ -17,7 +17,7 @@ package org.jivesoftware.smack.packet; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; /** * Represents XMPP presence packets. Every presence packet has a type, which is one of @@ -220,49 +220,35 @@ public class Presence extends Packet { this.language = language; } - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - if (status != null) { - buf.append("").append(StringUtils.escapeForXML(status)).append(""); + buf.attribute("type", type); } + buf.rightAngelBracket(); + + buf.optElement("status", status); if (priority != Integer.MIN_VALUE) { - buf.append("").append(priority).append(""); + buf.element("priority", Integer.toString(priority)); } if (mode != null && mode != Mode.available) { - buf.append("").append(mode).append(""); + buf.element("show", mode); } - - buf.append(this.getExtensionsXML()); + buf.append(getExtensionsXML()); // Add the error sub-packet, if there is one. XMPPError error = getError(); if (error != null) { buf.append(error.toXML()); } + buf.closeElement("presence"); - buf.append(""); - - return buf.toString(); + return buf; } public String toString() { diff --git a/core/src/main/java/org/jivesoftware/smack/packet/Registration.java b/core/src/main/java/org/jivesoftware/smack/packet/Registration.java index 1b81c9520..5e15be995 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/Registration.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/Registration.java @@ -19,6 +19,8 @@ package org.jivesoftware.smack.packet; import java.util.Map; +import org.jivesoftware.smack.util.XmlStringBuilder; + /** * Represents registration packets. An empty GET query will cause the server to return information * about it's registration support. SET queries can be used to create accounts or update @@ -85,23 +87,22 @@ public class Registration extends IQ { this.attributes = attributes; } - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - if (instructions != null) { - buf.append("").append(instructions).append(""); - } + @Override + public XmlStringBuilder getChildElementXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement("query"); + xml.xmlnsAttribute("jabber:iq:register"); + xml.rightAngelBracket(); + xml.optElement("instructions", instructions); if (attributes != null && attributes.size() > 0) { for (String name : attributes.keySet()) { String value = attributes.get(name); - buf.append("<").append(name).append(">"); - buf.append(value); - buf.append(""); + xml.element(name, value); } } // Add packet extensions, if any are defined. - buf.append(getExtensionsXML()); - buf.append(""); - return buf.toString(); + xml.append(getExtensionsXML()); + xml.closeElement("query"); + return xml; } } diff --git a/core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java b/core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java index 1e4271776..e72d95098 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/RosterPacket.java @@ -18,6 +18,7 @@ package org.jivesoftware.smack.packet; import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; import java.util.*; import java.util.concurrent.CopyOnWriteArraySet; @@ -65,22 +66,20 @@ public class RosterPacket extends IQ { } } - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); + public CharSequence getChildElementXML() { + XmlStringBuilder buf = new XmlStringBuilder(); + buf.halfOpenElement("query"); + buf.xmlnsAttribute("jabber:iq:roster"); + buf.optAttribute("ver", rosterVersion); + buf.rightAngelBracket(); + synchronized (rosterItems) { for (Item entry : rosterItems) { buf.append(entry.toXML()); } } - buf.append(""); - return buf.toString(); + buf.closeElement("query"); + return buf; } public String getVersion() { diff --git a/core/src/main/java/org/jivesoftware/smack/packet/Session.java b/core/src/main/java/org/jivesoftware/smack/packet/Session.java index a835a2e06..11cc184b5 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/Session.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/Session.java @@ -36,7 +36,8 @@ public class Session extends IQ { setType(IQ.Type.SET); } - public String getChildElementXML() { + @Override + public CharSequence getChildElementXML() { return ""; } } diff --git a/core/src/main/java/org/jivesoftware/smack/packet/XMPPError.java b/core/src/main/java/org/jivesoftware/smack/packet/XMPPError.java index 02a6fdb64..1560b139e 100644 --- a/core/src/main/java/org/jivesoftware/smack/packet/XMPPError.java +++ b/core/src/main/java/org/jivesoftware/smack/packet/XMPPError.java @@ -152,7 +152,7 @@ public class XMPPError { * * @return the error as XML. */ - public String toXML() { + public CharSequence toXML() { StringBuilder buf = new StringBuilder(); buf.append(" list; + + public LazyStringBuilder() { + list = new ArrayList(20); + } + + public LazyStringBuilder append(LazyStringBuilder lsb) { + list.addAll(lsb.list); + return this; + } + + @Override + public LazyStringBuilder append(CharSequence csq) { + assert csq != null; + list.add(csq); + return this; + } + + @Override + public LazyStringBuilder append(CharSequence csq, int start, int end) { + CharSequence subsequence = csq.subSequence(start, end); + list.add(subsequence); + return this; + } + + @Override + public LazyStringBuilder append(char c) { + list.add(Character.toString(c)); + return this; + } + + @Override + public int length() { + int length = 0; + for (CharSequence csq : list) { + length += csq.length(); + } + return length; + } + + @Override + public char charAt(int index) { + for (CharSequence csq : list) { + if (index < csq.length()) { + return csq.charAt(index); + } else { + index -= csq.length(); + } + } + throw new IndexOutOfBoundsException(); + } + + @Override + public CharSequence subSequence(int start, int end) { + return toString().subSequence(start, end); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(length()); + for (CharSequence csq : list) { + sb.append(csq); + } + return sb.toString(); + } +} diff --git a/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java b/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java index 07cab1082..f2c4572c5 100644 --- a/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java +++ b/core/src/main/java/org/jivesoftware/smack/util/StringUtils.java @@ -290,7 +290,7 @@ public class StringUtils { * @param string the string to escape. * @return the string with appropriate characters escaped. */ - public static String escapeForXML(final String string) { + public static CharSequence escapeForXML(final String string) { if (string == null) { return null; } @@ -339,7 +339,7 @@ public class StringUtils { if (i > last) { out.append(input, last, i - last); } - return out.toString(); + return out; } /** diff --git a/core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java b/core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java index 5ca8538c8..109187ced 100644 --- a/core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java +++ b/core/src/main/java/org/jivesoftware/smack/util/XmlStringBuilder.java @@ -16,12 +16,20 @@ */ package org.jivesoftware.smack.util; -public class XmlStringBuilder implements Appendable, CharSequence { +import org.jivesoftware.smack.packet.PacketExtension; - private final StringBuilder sb; +public class XmlStringBuilder implements Appendable, CharSequence { + public static final String RIGHT_ANGEL_BRACKET = Character.toString('>'); + + private final LazyStringBuilder sb; public XmlStringBuilder() { - sb = new StringBuilder(); + sb = new LazyStringBuilder(); + } + + public XmlStringBuilder(PacketExtension pe) { + this(); + prelude(pe); } /** @@ -29,11 +37,10 @@ public class XmlStringBuilder implements Appendable, CharSequence { * * @param name * @param content - * @return + * @return the XmlStringBuilder */ public XmlStringBuilder element(String name, String content) { - if (content == null) - return this; + assert content != null; openElement(name); escape(content); closeElement(name); @@ -41,8 +48,21 @@ public class XmlStringBuilder implements Appendable, CharSequence { } public XmlStringBuilder element(String name, Enum content) { + assert content != null; + element(name, content.name()); + return this; + } + + public XmlStringBuilder optElement(String name, String content) { if (content != null) { - element(name, content.name()); + element(name, content); + } + return this; + } + + public XmlStringBuilder optElement(String name, Enum content) { + if (content != null) { + element(name, content); } return this; } @@ -53,54 +73,111 @@ public class XmlStringBuilder implements Appendable, CharSequence { } public XmlStringBuilder openElement(String name) { - halfOpenElement(name).append('>'); + halfOpenElement(name).rightAngelBracket(); return this; } public XmlStringBuilder closeElement(String name) { - sb.append("'); + sb.append(""); return this; } + public XmlStringBuilder rightAngelBracket() { + sb.append(RIGHT_ANGEL_BRACKET); + return this; + } + /** * Does nothing if value is null. * * @param name * @param value - * @return + * @return the XmlStringBuilder */ public XmlStringBuilder attribute(String name, String value) { - if (value == null) - return this; + assert value != null; sb.append(' ').append(name).append("='"); escape(value); sb.append('\''); return this; } - public XmlStringBuilder xmlnsAttribute(String value) { - attribute("xmlns", value); + public XmlStringBuilder attribute(String name, Enum value) { + assert value != null; + attribute(name, value.name()); return this; } + public XmlStringBuilder optAttribute(String name, String value) { + if (value != null) { + attribute(name, value); + } + return this; + } + + public XmlStringBuilder optAttribute(String name, Enum value) { + if (value != null) { + attribute(name, value.name()); + } + return this; + } + + public XmlStringBuilder xmlnsAttribute(String value) { + optAttribute("xmlns", value); + return this; + } + + public XmlStringBuilder xmllangAttribute(String value) { + optAttribute("xml:lang", value); + return this; + } + public XmlStringBuilder escape(String text) { + assert text != null; sb.append(StringUtils.escapeForXML(text)); return this; } + public XmlStringBuilder prelude(PacketExtension pe) { + halfOpenElement(pe.getElementName()); + xmlnsAttribute(pe.getNamespace()); + return this; + } + + public XmlStringBuilder optAppend(CharSequence csq) { + if (csq != null) { + append(csq); + } + return this; + } + + public XmlStringBuilder append(XmlStringBuilder xsb) { + assert xsb != null; + sb.append(xsb.sb); + return this; + } + @Override public XmlStringBuilder append(CharSequence csq) { + assert csq != null; sb.append(csq); return this; } @Override public XmlStringBuilder append(CharSequence csq, int start, int end) { + assert csq != null; sb.append(csq, start, end); return this; } diff --git a/core/src/main/java/org/jivesoftware/smack/util/XmlUtils.java b/core/src/main/java/org/jivesoftware/smack/util/XmlUtils.java deleted file mode 100644 index cc8e0343f..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/XmlUtils.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * - * Copyright the original author or authors - * - * 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.util; - -/** - * Simple utility for XML. - * - * @author Robin Collier - */ -public class XmlUtils { - - static public void appendAttribute(StringBuilder builder, String att, String value) { - builder.append(" "); - builder.append(att); - builder.append("='"); - builder.append(value); - builder.append("'"); - } - -} diff --git a/core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java b/core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java index e1336856a..dab1d67ce 100644 --- a/core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java +++ b/core/src/test/java/org/jivesoftware/smack/packet/MessageTest.java @@ -54,7 +54,7 @@ public class MessageTest { Message messageTypeInConstructor = new Message(null, Message.Type.chat); messageTypeInConstructor.setPacketID(Packet.ID_NOT_AVAILABLE); assertEquals(type, messageTypeInConstructor.getType()); - assertXMLEqual(control, messageTypeInConstructor.toXML()); + assertXMLEqual(control, messageTypeInConstructor.toXML().toString()); controlBuilder = new StringBuilder(); controlBuilder.append("") @@ -161,7 +161,7 @@ public class PresenceTest { Presence presenceModeSet = getNewPresence(); presenceModeSet.setMode(mode2); assertEquals(mode2, presenceModeSet.getMode()); - assertXMLEqual(control, presenceModeSet.toXML()); + assertXMLEqual(control, presenceModeSet.toXML().toString()); } @Test @@ -189,7 +189,7 @@ public class PresenceTest { Presence presence = getNewPresence(); presence.setLanguage(lang); - assertXMLEqual(control, presence.toXML()); + assertXMLEqual(control, presence.toXML().toString()); } private static Presence getNewPresence() { diff --git a/core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java b/core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java index d34a20d92..e8e351d65 100644 --- a/core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java +++ b/core/src/test/java/org/jivesoftware/smack/util/PacketParserUtilsTest.java @@ -75,7 +75,7 @@ public class PacketParserUtilsTest { assertTrue(message.getBodyLanguages().isEmpty()); assertEquals(defaultLanguage, message.getBody(defaultLanguage)); assertNull(message.getBody(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has non-default language, body has no language control = XMLBuilder.create("message") @@ -94,7 +94,7 @@ public class PacketParserUtilsTest { assertTrue(message.getBodyLanguages().isEmpty()); assertEquals(otherLanguage, message.getBody(otherLanguage)); assertNull(message.getBody(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, body has no language control = XMLBuilder.create("message") @@ -112,7 +112,7 @@ public class PacketParserUtilsTest { assertTrue(message.getBodyLanguages().isEmpty()); assertEquals(defaultLanguage, message.getBody(defaultLanguage)); assertNull(message.getBody(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, body has default language control = XMLBuilder.create("message") @@ -133,7 +133,7 @@ public class PacketParserUtilsTest { assertNull(message.getBody(otherLanguage)); // body attribute xml:lang is unnecessary - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); // message has no language, body has non-default language control = XMLBuilder.create("message") @@ -153,7 +153,7 @@ public class PacketParserUtilsTest { assertTrue(message.getBodyLanguages().contains(otherLanguage)); assertEquals(otherLanguage, message.getBody(otherLanguage)); assertNull(message.getBody(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has default language, body has non-default language control = XMLBuilder.create("message") @@ -174,7 +174,7 @@ public class PacketParserUtilsTest { assertTrue(message.getBodyLanguages().contains(otherLanguage)); assertEquals(otherLanguage, message.getBody(otherLanguage)); assertNull(message.getBody(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has non-default language, body has default language control = XMLBuilder.create("message") @@ -195,7 +195,7 @@ public class PacketParserUtilsTest { assertTrue(message.getBodyLanguages().contains(defaultLanguage)); assertEquals(defaultLanguage, message.getBody(defaultLanguage)); assertNull(message.getBody(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); } @@ -225,7 +225,7 @@ public class PacketParserUtilsTest { assertTrue(message.getSubjectLanguages().isEmpty()); assertEquals(defaultLanguage, message.getSubject(defaultLanguage)); assertNull(message.getSubject(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has non-default language, subject has no language control = XMLBuilder.create("message") @@ -244,7 +244,7 @@ public class PacketParserUtilsTest { assertTrue(message.getSubjectLanguages().isEmpty()); assertEquals(otherLanguage, message.getSubject(otherLanguage)); assertNull(message.getSubject(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, subject has no language control = XMLBuilder.create("message") @@ -262,7 +262,7 @@ public class PacketParserUtilsTest { assertTrue(message.getSubjectLanguages().isEmpty()); assertEquals(defaultLanguage, message.getSubject(defaultLanguage)); assertNull(message.getSubject(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, subject has default language control = XMLBuilder.create("message") @@ -283,7 +283,7 @@ public class PacketParserUtilsTest { assertNull(message.getSubject(otherLanguage)); // subject attribute xml:lang is unnecessary - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); // message has no language, subject has non-default language control = XMLBuilder.create("message") @@ -303,7 +303,7 @@ public class PacketParserUtilsTest { assertTrue(message.getSubjectLanguages().contains(otherLanguage)); assertEquals(otherLanguage, message.getSubject(otherLanguage)); assertNull(message.getSubject(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has default language, subject has non-default language control = XMLBuilder.create("message") @@ -324,7 +324,7 @@ public class PacketParserUtilsTest { assertTrue(message.getSubjectLanguages().contains(otherLanguage)); assertEquals(otherLanguage, message.getSubject(otherLanguage)); assertNull(message.getSubject(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has non-default language, subject has default language control = XMLBuilder.create("message") @@ -345,7 +345,7 @@ public class PacketParserUtilsTest { assertTrue(message.getSubjectLanguages().contains(defaultLanguage)); assertEquals(defaultLanguage, message.getSubject(defaultLanguage)); assertNull(message.getSubject(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); } @@ -381,7 +381,7 @@ public class PacketParserUtilsTest { assertEquals(2, message.getBodies().size()); assertEquals(1, message.getBodyLanguages().size()); assertTrue(message.getBodyLanguages().contains(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has default language, first body no language, second body default language control = XMLBuilder.create("message") @@ -405,7 +405,7 @@ public class PacketParserUtilsTest { assertEquals(defaultLanguage, message.getBody(defaultLanguage)); assertEquals(1, message.getBodies().size()); assertEquals(0, message.getBodyLanguages().size()); - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); // message has non-default language, first body no language, second body default language control = XMLBuilder.create("message") @@ -430,7 +430,7 @@ public class PacketParserUtilsTest { assertEquals(2, message.getBodies().size()); assertEquals(1, message.getBodyLanguages().size()); assertTrue(message.getBodyLanguages().contains(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, first body no language, second body default language control = XMLBuilder.create("message") @@ -453,7 +453,7 @@ public class PacketParserUtilsTest { assertEquals(defaultLanguage, message.getBody(defaultLanguage)); assertEquals(1, message.getBodies().size()); assertEquals(0, message.getBodyLanguages().size()); - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); // message has no language, first body no language, second body other language control = XMLBuilder.create("message") @@ -477,7 +477,7 @@ public class PacketParserUtilsTest { assertEquals(otherLanguage, message.getBody(otherLanguage)); assertEquals(2, message.getBodies().size()); assertEquals(1, message.getBodyLanguages().size()); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, first body no language, second body no language control = XMLBuilder.create("message") @@ -499,7 +499,7 @@ public class PacketParserUtilsTest { assertEquals(defaultLanguage, message.getBody(defaultLanguage)); assertEquals(1, message.getBodies().size()); assertEquals(0, message.getBodyLanguages().size()); - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); } @@ -535,7 +535,7 @@ public class PacketParserUtilsTest { assertEquals(2, message.getSubjects().size()); assertEquals(1, message.getSubjectLanguages().size()); assertTrue(message.getSubjectLanguages().contains(otherLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has default language, first subject no language, second subject default language control = XMLBuilder.create("message") @@ -559,7 +559,7 @@ public class PacketParserUtilsTest { assertEquals(defaultLanguage, message.getSubject(defaultLanguage)); assertEquals(1, message.getSubjects().size()); assertEquals(0, message.getSubjectLanguages().size()); - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); // message has non-default language, first subject no language, second subject default language control = XMLBuilder.create("message") @@ -584,7 +584,7 @@ public class PacketParserUtilsTest { assertEquals(2, message.getSubjects().size()); assertEquals(1, message.getSubjectLanguages().size()); assertTrue(message.getSubjectLanguages().contains(defaultLanguage)); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, first subject no language, second subject default language control = XMLBuilder.create("message") @@ -607,7 +607,7 @@ public class PacketParserUtilsTest { assertEquals(defaultLanguage, message.getSubject(defaultLanguage)); assertEquals(1, message.getSubjects().size()); assertEquals(0, message.getSubjectLanguages().size()); - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); // message has no language, first subject no language, second subject other language control = XMLBuilder.create("message") @@ -631,7 +631,7 @@ public class PacketParserUtilsTest { assertEquals(otherLanguage, message.getSubject(otherLanguage)); assertEquals(2, message.getSubjects().size()); assertEquals(1, message.getSubjectLanguages().size()); - assertXMLEqual(control, message.toXML()); + assertXMLEqual(control, message.toXML().toString()); // message has no language, first subject no language, second subject no language control = XMLBuilder.create("message") @@ -653,7 +653,7 @@ public class PacketParserUtilsTest { assertEquals(defaultLanguage, message.getSubject(defaultLanguage)); assertEquals(1, message.getSubjects().size()); assertEquals(0, message.getSubjectLanguages().size()); - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); } @@ -679,9 +679,9 @@ public class PacketParserUtilsTest { + "Bad Message Body"; assertEquals(body, message.getBody()); - assertXMLNotEqual(control, message.toXML()); + assertXMLNotEqual(control, message.toXML().toString()); - DetailedDiff diffs = new DetailedDiff(new Diff(control, message.toXML())); + DetailedDiff diffs = new DetailedDiff(new Diff(control, message.toXML().toString())); // body has no namespace URI, span is escaped assertEquals(6, diffs.getAllDifferences().size()); @@ -754,7 +754,7 @@ public class PacketParserUtilsTest { .asString(outputProperties); Packet message = PacketParserUtils.parseMessage(TestUtils.getMessageParser(control)); - Diff xmlDiff = new Diff(control, message.toXML()); + Diff xmlDiff = new Diff(control, message.toXML().toString()); xmlDiff.overrideElementQualifier(new RecursiveElementNameAndTextQualifier()); assertTrue(xmlDiff.similar()); } @@ -765,7 +765,7 @@ public class PacketParserUtilsTest { Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza)); - assertXMLEqual(stanza, presence.toXML()); + assertXMLEqual(stanza, presence.toXML().toString()); } @SuppressWarnings("deprecation") @@ -775,7 +775,7 @@ public class PacketParserUtilsTest { Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza)); - assertXMLEqual(stanza, presence.toXML()); + assertXMLEqual(stanza, presence.toXML().toString()); assertEquals(Presence.Type.unsubscribed, presence.getType()); } @@ -789,7 +789,7 @@ public class PacketParserUtilsTest { + ""; Presence presence = PacketParserUtils.parsePresence(TestUtils.getPresenceParser(stanza)); - assertXMLEqual(stanza, presence.toXML()); + assertXMLEqual(stanza, presence.toXML().toString()); assertEquals(Presence.Type.unsubscribed, presence.getType()); assertEquals("dnd", presence.getMode().name()); assertEquals("en", presence.getLanguage()); diff --git a/core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java b/core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java index 2f62cb213..b20d8c16c 100644 --- a/core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java +++ b/core/src/test/java/org/jivesoftware/smack/util/StringUtilsTest.java @@ -35,39 +35,43 @@ public class StringUtilsTest { assertNull(StringUtils.escapeForXML(null)); input = ""; - assertEquals("<b>", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("<b>", StringUtils.escapeForXML(input)); input = "\""; - assertEquals(""", StringUtils.escapeForXML(input)); + assertCharSequenceEquals(""", StringUtils.escapeForXML(input)); input = "&"; - assertEquals("&", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("&", StringUtils.escapeForXML(input)); input = "\n\t\r"; - assertEquals("<b>\n\t\r</b>", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("<b>\n\t\r</b>", StringUtils.escapeForXML(input)); input = " & "; - assertEquals(" & ", StringUtils.escapeForXML(input)); + assertCharSequenceEquals(" & ", StringUtils.escapeForXML(input)); input = " \" "; - assertEquals(" " ", StringUtils.escapeForXML(input)); + assertCharSequenceEquals(" " ", StringUtils.escapeForXML(input)); input = "> of me <"; - assertEquals("> of me <", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("> of me <", StringUtils.escapeForXML(input)); input = "> of me & you<"; - assertEquals("> of me & you<", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("> of me & you<", StringUtils.escapeForXML(input)); input = "& <"; - assertEquals("& <", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("& <", StringUtils.escapeForXML(input)); input = "&"; - assertEquals("&", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("&", StringUtils.escapeForXML(input)); input = "It's a good day today"; - assertEquals("It's a good day today", StringUtils.escapeForXML(input)); + assertCharSequenceEquals("It's a good day today", StringUtils.escapeForXML(input)); } + public static void assertCharSequenceEquals(CharSequence expected, CharSequence actual) { + assertEquals(expected.toString(), actual.toString()); + } + @Test public void testHash() { // Test null diff --git a/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java b/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java index 218caf67d..4159a3430 100644 --- a/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java +++ b/debug/src/main/java/org/jivesoftware/smackx/debugger/EnhancedDebugger.java @@ -801,7 +801,7 @@ public class EnhancedDebugger implements SmackDebugger { messagesTable.addRow( new Object[]{ - formatXML(packet.toXML()), + formatXML(packet.toXML().toString()), dateFormatter.format(new Date()), packetReceivedIcon, packetTypeIcon, @@ -862,7 +862,7 @@ public class EnhancedDebugger implements SmackDebugger { messagesTable.addRow( new Object[]{ - formatXML(packet.toXML()), + formatXML(packet.toXML().toString()), dateFormatter.format(new Date()), packetSentIcon, packetTypeIcon, diff --git a/extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java b/extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java index 8b889a09b..73774b75c 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/address/MultipleRecipientManager.java @@ -336,7 +336,7 @@ public class MultipleRecipientManager { */ private static class PacketCopy extends Packet { - private String text; + private CharSequence text; /** * Create a copy of a packet with the text to send. The passed text must be a valid text to @@ -344,11 +344,12 @@ public class MultipleRecipientManager { * * @param text the whole text of the packet to send */ - public PacketCopy(String text) { + public PacketCopy(CharSequence text) { this.text = text; } - public String toXML() { + @Override + public CharSequence toXML() { return text; } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java b/extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java index eb1820ad8..c8d90e1a2 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/caps/cache/SimpleDirectoryPersistentCache.java @@ -128,7 +128,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache private static void writeInfoToFile(File file, DiscoverInfo info) throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream(file)); try { - dos.writeUTF(info.toXML()); + dos.writeUTF(info.toXML().toString()); } finally { dos.close(); } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/caps/packet/CapsExtension.java b/extensions/src/main/java/org/jivesoftware/smackx/caps/packet/CapsExtension.java index ef93a60aa..6746e6a63 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/caps/packet/CapsExtension.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/caps/packet/CapsExtension.java @@ -17,6 +17,7 @@ package org.jivesoftware.smackx.caps.packet; import org.jivesoftware.smack.packet.PacketExtension; +import org.jivesoftware.smack.util.XmlStringBuilder; import org.jivesoftware.smackx.caps.EntityCapsManager; public class CapsExtension implements PacketExtension { @@ -56,10 +57,10 @@ public class CapsExtension implements PacketExtension { * ver='QgayPKawpkPSDYmwT/WM94uAlu0='/> * */ - public String toXML() { - return "<" + EntityCapsManager.ELEMENT + " xmlns=\"" + EntityCapsManager.NAMESPACE + "\" " + - "hash=\"" + hash + "\" " + - "node=\"" + node + "\" " + - "ver=\"" + ver + "\"/>"; + public CharSequence toXML() { + XmlStringBuilder xml = new XmlStringBuilder(this); + xml.attribute("hash", hash).attribute("node", node).attribute("ver", ver); + xml.closeEmptyElement(); + return xml; } } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java b/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java index c8e856f30..910210901 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverInfo.java @@ -18,7 +18,7 @@ package org.jivesoftware.smackx.disco.packet; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; import java.util.Collection; import java.util.Collections; @@ -186,29 +186,27 @@ public class DiscoverInfo extends IQ { return false; } - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); + @Override + public CharSequence getChildElementXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement("query"); + xml.xmlnsAttribute(NAMESPACE); + xml.optAttribute("node", getNode()); + xml.rightAngelBracket(); synchronized (identities) { for (Identity identity : identities) { - buf.append(identity.toXML()); + xml.append(identity.toXML()); } } synchronized (features) { for (Feature feature : features) { - buf.append(feature.toXML()); + xml.append(feature.toXML()); } } // Add packet extensions, if any are defined. - buf.append(getExtensionsXML()); - buf.append(""); - return buf.toString(); + xml.append(getExtensionsXML()); + xml.closeElement("query"); + return xml; } /** @@ -358,22 +356,15 @@ public class DiscoverInfo extends IQ { return lang; } - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - return buf.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement("identity"); + xml.xmllangAttribute(lang); + xml.attribute("category", category); + xml.attribute("name", name); + xml.optAttribute("type", type); + xml.closeEmptyElement(); + return xml; } /** @@ -488,10 +479,12 @@ public class DiscoverInfo extends IQ { return variable; } - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - return buf.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement("feature"); + xml.attribute("var", variable); + xml.closeEmptyElement(); + return xml; } public boolean equals(Object obj) { diff --git a/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java b/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java index dc8b89a70..48b5219bf 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/disco/packet/DiscoverItems.java @@ -18,7 +18,7 @@ package org.jivesoftware.smackx.disco.packet; import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; import java.util.Collection; import java.util.Collections; @@ -102,22 +102,20 @@ public class DiscoverItems extends IQ { this.node = node; } - public String getChildElementXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); + public XmlStringBuilder getChildElementXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement("query"); + xml.xmlnsAttribute(NAMESPACE); + xml.optAttribute("node", getNode()); + xml.rightAngelBracket(); + synchronized (items) { for (Item item : items) { - buf.append(item.toXML()); + xml.append(item.toXML()); } } - buf.append(""); - return buf.toString(); + xml.closeElement("query"); + return xml; } /** @@ -231,20 +229,15 @@ public class DiscoverItems extends IQ { this.action = action; } - public String toXML() { - StringBuilder buf = new StringBuilder(); - buf.append(""); - return buf.toString(); + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement("item"); + xml.attribute("jid", entityID); + xml.optAttribute("name", name); + xml.optAttribute("node", node); + xml.optAttribute("action", action); + xml.closeEmptyElement(); + return xml; } } } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/AffiliationsExtension.java b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/AffiliationsExtension.java index 86cf25045..739fd6f8b 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/AffiliationsExtension.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/AffiliationsExtension.java @@ -46,7 +46,7 @@ public class AffiliationsExtension extends NodeExtension } @Override - public String toXML() + public CharSequence toXML() { if ((items == null) || (items.size() == 0)) { diff --git a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/FormNode.java b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/FormNode.java index a4c476b2a..ac8256219 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/FormNode.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/FormNode.java @@ -73,7 +73,7 @@ public class FormNode extends NodeExtension } @Override - public String toXML() + public CharSequence toXML() { if (configForm == null) { diff --git a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemsExtension.java b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemsExtension.java index 8613fe61b..64dca28dd 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemsExtension.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/ItemsExtension.java @@ -151,7 +151,7 @@ public class ItemsExtension extends NodeExtension implements EmbeddedPacketExten } @Override - public String toXML() + public CharSequence toXML() { if ((items == null) || (items.size() == 0)) { diff --git a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/NodeExtension.java b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/NodeExtension.java index e0ed017ca..3e16b79a5 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/NodeExtension.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/NodeExtension.java @@ -75,7 +75,7 @@ public class NodeExtension implements PacketExtension return element.getNamespace().getXmlns(); } - public String toXML() + public CharSequence toXML() { return '<' + getElementName() + (node == null ? "" : " node='" + node + '\'') + "/>"; } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/OptionsExtension.java b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/OptionsExtension.java index fa9827e67..21d30bcc8 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/OptionsExtension.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/OptionsExtension.java @@ -16,7 +16,7 @@ */ package org.jivesoftware.smackx.pubsub; -import org.jivesoftware.smack.util.XmlUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; /** * A packet extension representing the options element. @@ -54,22 +54,15 @@ public class OptionsExtension extends NodeExtension { return id; } - - @Override - public String toXML() - { - StringBuilder builder = new StringBuilder("<"); - builder.append(getElementName()); - XmlUtils.appendAttribute(builder, "jid", jid); - - if (getNode() != null) - XmlUtils.appendAttribute(builder, "node", getNode()); - - if (id != null) - XmlUtils.appendAttribute(builder, "subid", id); - - builder.append("/>"); - return builder.toString(); - } + @Override + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement(getElementName()); + xml.attribute("jid", jid); + xml.optAttribute("node", getNode()); + xml.optAttribute("subid", id); + xml.closeEmptyElement(); + return xml; + } } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscriptionsExtension.java b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscriptionsExtension.java index be739be2f..7ab93348b 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscriptionsExtension.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/SubscriptionsExtension.java @@ -66,7 +66,7 @@ public class SubscriptionsExtension extends NodeExtension } @Override - public String toXML() + public CharSequence toXML() { if ((items == null) || (items.size() == 0)) { diff --git a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/UnsubscribeExtension.java b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/UnsubscribeExtension.java index ff3426df7..a5536237c 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/pubsub/UnsubscribeExtension.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/pubsub/UnsubscribeExtension.java @@ -16,7 +16,7 @@ */ package org.jivesoftware.smackx.pubsub; -import org.jivesoftware.smack.util.XmlUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; /** @@ -55,22 +55,15 @@ public class UnsubscribeExtension extends NodeExtension { return id; } - - @Override - public String toXML() - { - StringBuilder builder = new StringBuilder("<"); - builder.append(getElementName()); - XmlUtils.appendAttribute(builder, "jid", jid); - - if (getNode() != null) - XmlUtils.appendAttribute(builder, "node", getNode()); - - if (id != null) - XmlUtils.appendAttribute(builder, "subid", id); - - builder.append("/>"); - return builder.toString(); - } + @Override + public XmlStringBuilder toXML() { + XmlStringBuilder xml = new XmlStringBuilder(); + xml.halfOpenElement(getElementName()); + xml.attribute("jid", jid); + xml.optAttribute("node", getNode()); + xml.optAttribute("subid", id); + xml.closeEmptyElement(); + return xml; + } } diff --git a/extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java b/extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java index 42a5051dc..2bd287d51 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/vcardtemp/packet/VCard.java @@ -844,11 +844,11 @@ public class VCard extends IQ { appendTag(tag, null, null, hasContent, builder); } - private void appendTag(String tag, final String tagText) { + private void appendTag(String tag, final CharSequence tagText) { if (tagText == null) return; final ContentBuilder contentBuilder = new ContentBuilder() { public void addTagContent() { - sb.append(tagText.trim()); + sb.append(tagText.toString().trim()); } }; appendTag(tag, true, contentBuilder); diff --git a/extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java b/extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java index dfc64a694..d6166366e 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/xdata/FormField.java @@ -18,6 +18,7 @@ package org.jivesoftware.smackx.xdata; import org.jivesoftware.smack.util.StringUtils; +import org.jivesoftware.smack.util.XmlStringBuilder; import java.util.ArrayList; import java.util.Collections; @@ -264,15 +265,13 @@ public class FormField { } public String toXML() { - StringBuilder buf = new StringBuilder(); + XmlStringBuilder buf = new XmlStringBuilder(); buf.append(" i = getValues(); i.hasNext();) { - buf.append("").append(i.next()).append(""); + buf.element("value", i.next()); } // Loop through all the values and append them to the string buffer for (Iterator