Merge branch 'pr-2831' into master

[core] Fix XMLRenderer newlines when running under IBM Java #2831
This commit is contained in:
Andreas Dangel
2020-10-22 09:44:20 +02:00
2 changed files with 46 additions and 13 deletions

View File

@ -22,6 +22,9 @@ This is a {{ site.pmd.release_type }} release.
the Java VM, which is bad, if the VM runs an application server which many independent applications. the Java VM, which is bad, if the VM runs an application server which many independent applications.
### Fixed Issues ### Fixed Issues
* core
* [#2831](https://github.com/pmd/pmd/pull/2831): \[core] Fix XMLRenderer newlines when running under IBM Java
* java-errorprone * java-errorprone
* [#2157](https://github.com/pmd/pmd/issues/2157): \[java] Improve DoNotCallSystemExit: permit call in main(), flag System.halt * [#2157](https://github.com/pmd/pmd/issues/2157): \[java] Improve DoNotCallSystemExit: permit call in main(), flag System.halt
* [#2764](https://github.com/pmd/pmd/issues/2764): \[java] CloseResourceRule does not recognize multiple assignment done to resource * [#2764](https://github.com/pmd/pmd/issues/2764): \[java] CloseResourceRule does not recognize multiple assignment done to resource

View File

@ -46,6 +46,7 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
private XMLStreamWriter xmlWriter; private XMLStreamWriter xmlWriter;
private OutputStream stream; private OutputStream stream;
private byte[] lineSeparator;
public XMLRenderer() { public XMLRenderer() {
super(NAME, "XML format."); super(NAME, "XML format.");
@ -65,10 +66,11 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
@Override @Override
public void start() throws IOException { public void start() throws IOException {
String encoding = getProperty(ENCODING); String encoding = getProperty(ENCODING);
lineSeparator = PMD.EOL.getBytes(encoding);
try { try {
xmlWriter.writeStartDocument(encoding, "1.0"); xmlWriter.writeStartDocument(encoding, "1.0");
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.setDefaultNamespace(PMD_REPORT_NS_URI); xmlWriter.setDefaultNamespace(PMD_REPORT_NS_URI);
xmlWriter.writeStartElement(PMD_REPORT_NS_URI, "pmd"); xmlWriter.writeStartElement(PMD_REPORT_NS_URI, "pmd");
xmlWriter.writeDefaultNamespace(PMD_REPORT_NS_URI); xmlWriter.writeDefaultNamespace(PMD_REPORT_NS_URI);
@ -84,6 +86,33 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
} }
} }
/**
* Outputs a platform dependent line separator.
*
* @throws XMLStreamException if XMLStreamWriter couldn't be flushed.
* @throws IOException if an I/O error occurs.
*/
private void writeNewLine() throws XMLStreamException, IOException {
/*
* Note: we are not using xmlWriter.writeCharacters(PMD.EOL), because some
* XMLStreamWriter implementations might do extra encoding for \r and/or \n.
* Notably IBM's Java 8 will escape "\r" with "
" which will render an
* invalid XML document. IBM's Java 8 would also output a platform dependent
* line separator when writing "\n" which results under Windows, that "\r"
* actually is written twice (once escaped, once raw).
*
* Note2: Before writing the raw bytes to the underlying stream, we need
* to flush XMLStreamWriter. Notably IBM's Java 8 might still need to output
* data.
*
* Note3: Before writing the raw bytes, we issue a empty writeCharacters,
* so that any open tags are closed and we are ready for writing raw bytes.
*/
xmlWriter.writeCharacters("");
xmlWriter.flush();
stream.write(lineSeparator);
}
@Override @Override
public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException { public void renderFileViolations(Iterator<RuleViolation> violations) throws IOException {
String filename = null; String filename = null;
@ -100,10 +129,10 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
xmlWriter.writeEndElement(); xmlWriter.writeEndElement();
} }
filename = nextFilename; filename = nextFilename;
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeStartElement("file"); xmlWriter.writeStartElement("file");
xmlWriter.writeAttribute("name", filename); xmlWriter.writeAttribute("name", filename);
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
} }
xmlWriter.writeStartElement("violation"); xmlWriter.writeStartElement("violation");
@ -119,11 +148,11 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
maybeAdd("variable", rv.getVariableName()); maybeAdd("variable", rv.getVariableName());
maybeAdd("externalInfoUrl", rv.getRule().getExternalInfoUrl()); maybeAdd("externalInfoUrl", rv.getRule().getExternalInfoUrl());
xmlWriter.writeAttribute("priority", String.valueOf(rv.getRule().getPriority().getPriority())); xmlWriter.writeAttribute("priority", String.valueOf(rv.getRule().getPriority().getPriority()));
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeCharacters(StringUtil.removedInvalidXml10Characters(rv.getDescription())); xmlWriter.writeCharacters(StringUtil.removedInvalidXml10Characters(rv.getDescription()));
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeEndElement(); xmlWriter.writeEndElement();
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
} }
if (filename != null) { // Not first file ? if (filename != null) { // Not first file ?
xmlWriter.writeEndElement(); xmlWriter.writeEndElement();
@ -138,20 +167,20 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
try { try {
// errors // errors
for (Report.ProcessingError pe : errors) { for (Report.ProcessingError pe : errors) {
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeStartElement("error"); xmlWriter.writeStartElement("error");
xmlWriter.writeAttribute("filename", determineFileName(pe.getFile())); xmlWriter.writeAttribute("filename", determineFileName(pe.getFile()));
xmlWriter.writeAttribute("msg", pe.getMsg()); xmlWriter.writeAttribute("msg", pe.getMsg());
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeCData(pe.getDetail()); xmlWriter.writeCData(pe.getDetail());
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeEndElement(); xmlWriter.writeEndElement();
} }
// suppressed violations // suppressed violations
if (showSuppressedViolations) { if (showSuppressedViolations) {
for (Report.SuppressedViolation s : suppressed) { for (Report.SuppressedViolation s : suppressed) {
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeStartElement("suppressedviolation"); xmlWriter.writeStartElement("suppressedviolation");
xmlWriter.writeAttribute("filename", determineFileName(s.getRuleViolation().getFilename())); xmlWriter.writeAttribute("filename", determineFileName(s.getRuleViolation().getFilename()));
xmlWriter.writeAttribute("suppressiontype", s.suppressedByNOPMD() ? "nopmd" : "annotation"); xmlWriter.writeAttribute("suppressiontype", s.suppressedByNOPMD() ? "nopmd" : "annotation");
@ -163,14 +192,15 @@ public class XMLRenderer extends AbstractIncrementingRenderer {
// config errors // config errors
for (final Report.ConfigurationError ce : configErrors) { for (final Report.ConfigurationError ce : configErrors) {
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeEmptyElement("configerror"); xmlWriter.writeEmptyElement("configerror");
xmlWriter.writeAttribute("rule", ce.rule().getName()); xmlWriter.writeAttribute("rule", ce.rule().getName());
xmlWriter.writeAttribute("msg", ce.issue()); xmlWriter.writeAttribute("msg", ce.issue());
} }
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeEndElement(); // </pmd> xmlWriter.writeEndElement(); // </pmd>
xmlWriter.writeCharacters(PMD.EOL); writeNewLine();
xmlWriter.writeEndDocument();
xmlWriter.flush(); xmlWriter.flush();
} catch (XMLStreamException e) { } catch (XMLStreamException e) {
throw new IOException(e); throw new IOException(e);