XmlStringBuilder: Map all XML serialization to appendXmlTo()

this is now the single place where serializatin happens.
This commit is contained in:
Florian Schmaus 2019-09-21 22:56:20 +02:00
parent 6d7b2b70e8
commit 002d060584
2 changed files with 39 additions and 14 deletions

View File

@ -18,9 +18,10 @@ package org.jivesoftware.smack.util;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.Iterator; import java.util.List;
import org.jivesoftware.smack.packet.Element; import org.jivesoftware.smack.packet.Element;
import org.jivesoftware.smack.packet.ExtensionElement; import org.jivesoftware.smack.packet.ExtensionElement;
@ -606,6 +607,17 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
return toString().hashCode(); return toString().hashCode();
} }
private static final class WrappedIoException extends RuntimeException {
private static final long serialVersionUID = 1L;
private final IOException wrappedIoException;
private WrappedIoException(IOException wrappedIoException) {
this.wrappedIoException = wrappedIoException;
}
}
/** /**
* Write the contents of this <code>XmlStringBuilder</code> to a {@link Writer}. This will write * Write the contents of this <code>XmlStringBuilder</code> to a {@link Writer}. This will write
* the single parts one-by-one, avoiding allocation of a big continuous memory block holding the * the single parts one-by-one, avoiding allocation of a big continuous memory block holding the
@ -620,10 +632,25 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
.withNamespace(enclosingNamespace) .withNamespace(enclosingNamespace)
.build(); .build();
appendXmlTo(writer, enclosingXmlEnvironment); appendXmlTo(writer, enclosingXmlEnvironment);
try {
appendXmlTo(csq -> {
try {
writer.append(csq);
} catch (IOException e) {
throw new WrappedIoException(e);
}
}, enclosingXmlEnvironment);
} catch (WrappedIoException e) {
throw e.wrappedIoException;
}
} }
public Iterator<CharSequence> getCharSequenceIterator() { public List<CharSequence> toList(XmlEnvironment enclosingXmlEnvironment) {
return sb.getAsList().iterator(); List<CharSequence> res = new ArrayList<>(sb.getAsList().size());
appendXmlTo(csq -> res.add(csq), enclosingXmlEnvironment);
return res;
} }
@Override @Override
@ -631,29 +658,26 @@ public class XmlStringBuilder implements Appendable, CharSequence, Element {
// This is only the potential length, since the actual length depends on the given XmlEnvironment. // This is only the potential length, since the actual length depends on the given XmlEnvironment.
int potentialLength = length(); int potentialLength = length();
StringBuilder res = new StringBuilder(potentialLength); StringBuilder res = new StringBuilder(potentialLength);
try {
appendXmlTo(res, enclosingXmlEnvironment); appendXmlTo(csq -> res.append(csq), enclosingXmlEnvironment);
} catch (IOException e) {
// Should never happen.
throw new AssertionError(e);
}
return res; return res;
} }
private void appendXmlTo(Appendable appendable, XmlEnvironment enclosingXmlEnvironment) throws IOException { private void appendXmlTo(Consumer<CharSequence> charSequenceSink, XmlEnvironment enclosingXmlEnvironment) {
for (CharSequence csq : sb.getAsList()) { for (CharSequence csq : sb.getAsList()) {
if (csq instanceof XmlStringBuilder) { if (csq instanceof XmlStringBuilder) {
((XmlStringBuilder) csq).appendXmlTo(appendable, enclosingXmlEnvironment); ((XmlStringBuilder) csq).appendXmlTo(charSequenceSink, enclosingXmlEnvironment);
} }
else if (csq instanceof XmlNsAttribute) { else if (csq instanceof XmlNsAttribute) {
XmlNsAttribute xmlNsAttribute = (XmlNsAttribute) csq; XmlNsAttribute xmlNsAttribute = (XmlNsAttribute) csq;
if (!xmlNsAttribute.value.equals(enclosingXmlEnvironment.getEffectiveNamespace())) { if (!xmlNsAttribute.value.equals(enclosingXmlEnvironment.getEffectiveNamespace())) {
appendable.append(xmlNsAttribute); charSequenceSink.accept(xmlNsAttribute);
enclosingXmlEnvironment = new XmlEnvironment(xmlNsAttribute.value); enclosingXmlEnvironment = new XmlEnvironment(xmlNsAttribute.value);
} }
} }
else { else {
appendable.append(csq); charSequenceSink.accept(csq);
} }
} }
} }

View File

@ -82,6 +82,7 @@ import org.jivesoftware.smack.packet.StreamOpen;
import org.jivesoftware.smack.packet.TlsFailure; import org.jivesoftware.smack.packet.TlsFailure;
import org.jivesoftware.smack.packet.TlsProceed; import org.jivesoftware.smack.packet.TlsProceed;
import org.jivesoftware.smack.packet.TopLevelStreamElement; import org.jivesoftware.smack.packet.TopLevelStreamElement;
import org.jivesoftware.smack.packet.XmlEnvironment;
import org.jivesoftware.smack.sasl.SASLErrorException; import org.jivesoftware.smack.sasl.SASLErrorException;
import org.jivesoftware.smack.util.ArrayBlockingQueueWithShutdown; import org.jivesoftware.smack.util.ArrayBlockingQueueWithShutdown;
import org.jivesoftware.smack.util.Async; import org.jivesoftware.smack.util.Async;
@ -509,7 +510,7 @@ public class XmppNioTcpConnection extends AbstractXmppNioConnection {
CharSequence nextCharSequence = currentlyOutgonigTopLevelStreamElement.toXML(StreamOpen.CLIENT_NAMESPACE); CharSequence nextCharSequence = currentlyOutgonigTopLevelStreamElement.toXML(StreamOpen.CLIENT_NAMESPACE);
if (nextCharSequence instanceof XmlStringBuilder) { if (nextCharSequence instanceof XmlStringBuilder) {
XmlStringBuilder xmlStringBuilder = (XmlStringBuilder) nextCharSequence; XmlStringBuilder xmlStringBuilder = (XmlStringBuilder) nextCharSequence;
outgoingCharSequenceIterator = xmlStringBuilder.getCharSequenceIterator(); outgoingCharSequenceIterator = xmlStringBuilder.toList(XmlEnvironment.EMPTY).iterator();
} else { } else {
outgoingCharSequenceIterator = Collections.singletonList(nextCharSequence).iterator(); outgoingCharSequenceIterator = Collections.singletonList(nextCharSequence).iterator();
} }