The writePayload method (reproduced below) can be asked to pretty print
XML of any size, causing (I think) at least three copies of potentially
huge XML in memory.
The problem is that the limit is applied after the XML is formatted
(which it has to be, otherwise the data wouldn't be valid XML and
wouldn't be formattable).
Also, swriter.toString is called twice - which I assume means two more
copies of the data.
Would it be safer to disable pretty printing if cos.size() > limit ?
Or even to have a separate limit just for this purpose (i.e. never
pretty print more than 10MB unless the user has set limit >10MB).
As a side issue, two copies of the data could be removed by accessing
the StringBuffer directly rather than calling toString (example at the
end of this email), but I think the danger is with doing any pretty
printing of an unknown size.
Happy to submit a patch if folks agree it's an issue.
Jim
protected void writePayload(StringBuilder builder,
CachedOutputStream cos, String encoding, String contentType)
throws Exception {
// Just transform the XML message when the cos has content
if (isPrettyLogging() && (contentType != null &&
contentType.indexOf("xml") >= 0) && cos.size() > 0) {
Transformer serializer = XMLUtils.newTransformer(2);
// Setup indenting to "pretty print"
serializer.setOutputProperty(OutputKeys.INDENT, "yes");
serializer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
StringWriter swriter = new StringWriter();
serializer.transform(new
StreamSource(cos.getInputStream()), new StreamResult(swriter));
String result = swriter.toString();
if (result.length() < limit || limit == -1) {
builder.append(swriter.toString());
} else {
builder.append(swriter.toString().substring(0, limit));
}
} else {
if (StringUtils.isEmpty(encoding)) {
cos.writeCacheTo(builder, limit);
} else {
cos.writeCacheTo(builder, encoding, limit);
}
}
}
Change to remove calls to toString():
StringBuffer swBuffer = swriter.getBuffer();
if (swBuffer.length() < limit || limit == -1) {
builder.append(swBuffer.toString());
} else {
builder.append(swBuffer.substring(0, limit));
}