This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new dde821cf71 NIFI-6498 Update TransformXml to send errors to Component
Log
dde821cf71 is described below
commit dde821cf713ef7d77c627586b2a1d5bcde3ac5e3
Author: dan-s1 <[email protected]>
AuthorDate: Mon Dec 19 21:15:08 2022 +0000
NIFI-6498 Update TransformXml to send errors to Component Log
This closes #6798
Signed-off-by: David Handermann <[email protected]>
---
.../nifi-standard-processors/pom.xml | 1 +
.../nifi/processors/standard/TransformXml.java | 38 ++++++++++++++-
.../nifi/processors/standard/TestTransformXml.java | 55 ++++++++++++++++++++++
.../test/resources/TestTransformXml/employee.html | 35 ++++++++++++++
.../test/resources/TestTransformXml/employee.xml | 35 ++++++++++++++
.../employeeMessageNonTerminate.xsl | 50 ++++++++++++++++++++
.../TestTransformXml/employeeMessageTerminate.xsl | 50 ++++++++++++++++++++
.../TestTransformXml/nonMatchingEndTag.xsl | 35 ++++++++++++++
8 files changed, 297 insertions(+), 2 deletions(-)
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
index 24a589be72..c5ad98209a 100644
--- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
+++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
@@ -611,6 +611,7 @@
<exclude>src/test/resources/TestTransformXml/math.html</exclude>
<exclude>src/test/resources/TestTransformXml/tokens.csv</exclude>
<exclude>src/test/resources/TestTransformXml/tokens.xml</exclude>
+
<exclude>src/test/resources/TestTransformXml/employee.html</exclude>
<exclude>src/test/resources/TestUnpackContent/folder/cal.txt</exclude>
<exclude>src/test/resources/TestUnpackContent/folder/date.txt</exclude>
<exclude>src/test/resources/TestUnpackContent/data.flowfilev2</exclude>
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java
index 79a345ef8f..2896e54dfe 100644
---
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/TransformXml.java
@@ -38,6 +38,7 @@ import org.apache.nifi.expression.AttributeExpression;
import org.apache.nifi.expression.ExpressionLanguageScope;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.logging.ComponentLog;
+import org.apache.nifi.logging.LogLevel;
import org.apache.nifi.lookup.LookupFailureException;
import org.apache.nifi.lookup.LookupService;
import org.apache.nifi.lookup.StringLookupService;
@@ -55,12 +56,14 @@ import
org.apache.nifi.xml.processing.stream.XMLStreamReaderProvider;
import javax.xml.XMLConstants;
import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.ErrorListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
@@ -235,7 +238,7 @@ public class TransformXml extends AbstractProcessor {
.valid(false)
.subject(XSLT_CONTROLLER.getDisplayName())
.explanation("This processor requires a key-value
lookup service supporting exactly one required key, was: " +
- (requiredKeys == null ? "null" :
String.valueOf(requiredKeys.size())))
+ (requiredKeys == null ? "null" :
String.valueOf(requiredKeys.size())))
.build());
}
}
@@ -283,7 +286,7 @@ public class TransformXml extends AbstractProcessor {
final StopWatch stopWatch = new StopWatch(true);
final String path = context.getProperty(XSLT_FILE_NAME).isSet()
?
context.getProperty(XSLT_FILE_NAME).evaluateAttributeExpressions(original).getValue()
- :
context.getProperty(XSLT_CONTROLLER_KEY).evaluateAttributeExpressions(original).getValue();
+ :
context.getProperty(XSLT_CONTROLLER_KEY).evaluateAttributeExpressions(original).getValue();
try {
final FlowFile transformed = session.write(original, (inputStream,
outputStream) -> {
@@ -298,6 +301,7 @@ public class TransformXml extends AbstractProcessor {
final Transformer transformer = templates.newTransformer();
final String indentProperty =
context.getProperty(INDENT_OUTPUT).asBoolean() ? "yes" : "no";
transformer.setOutputProperty(OutputKeys.INDENT,
indentProperty);
+ transformer.setErrorListener(getErrorListenerLogger());
// pass all dynamic properties to the transformer
for (final Map.Entry<PropertyDescriptor, String> entry :
context.getProperties().entrySet()) {
@@ -323,6 +327,10 @@ public class TransformXml extends AbstractProcessor {
}
}
+ private ErrorListenerLogger getErrorListenerLogger() {
+ return new ErrorListenerLogger(getLogger());
+ }
+
@SuppressWarnings("unchecked")
private Templates newTemplates(final ProcessContext context, final String
path) throws TransformerConfigurationException, LookupFailureException {
final boolean secureProcessing =
context.getProperty(SECURE_PROCESSING).asBoolean();
@@ -341,6 +349,8 @@ public class TransformXml extends AbstractProcessor {
factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-parameter-entities",
false);
factory.setFeature("http://saxon.sf.net/feature/parserFeature?uri=http://xml.org/sax/features/external-general-entities",
false);
}
+ factory.setErrorListener(getErrorListenerLogger());
+
return factory;
}
@@ -372,4 +382,28 @@ public class TransformXml extends AbstractProcessor {
throw new TransformerConfigurationException("XSLT Source Stream
Reader creation failed", e);
}
}
+
+ private static class ErrorListenerLogger implements ErrorListener {
+ private final ComponentLog logger;
+
+ ErrorListenerLogger(ComponentLog logger) {
+ this.logger = logger;
+ }
+
+ @Override
+ public void warning(TransformerException exception) {
+ logger.warn(exception.getMessageAndLocation(), exception);
+ }
+
+ @Override
+ public void error(TransformerException exception) {
+ logger.error(exception.getMessageAndLocation(), exception);
+ }
+
+ @Override
+ public void fatalError(TransformerException exception) throws
TransformerException {
+ logger.log(LogLevel.FATAL, exception.getMessageAndLocation(),
exception);
+ throw exception;
+ }
+ }
}
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java
index 2962007a64..d91d7eaff8 100644
---
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestTransformXml.java
@@ -18,6 +18,7 @@ package org.apache.nifi.processors.standard;
import org.apache.nifi.lookup.SimpleKeyValueLookupService;
import org.apache.nifi.reporting.InitializationException;
+import org.apache.nifi.util.MockComponentLog;
import org.apache.nifi.util.MockFlowFile;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
@@ -32,6 +33,9 @@ import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
public class TestTransformXml {
@Test
@@ -297,4 +301,55 @@ public class TestTransformXml {
transformed.assertContentEquals("<?xml version=\"1.0\"
encoding=\"UTF-8\"?>");
}
+
+ @Test
+ public void testNonMatchingTemplateTag() throws IOException {
+ final TestRunner runner = TestRunners.newTestRunner(new
TransformXml());
+ runner.setProperty("header", "Test for mod");
+ runner.setProperty(TransformXml.XSLT_FILE_NAME,
"src/test/resources/TestTransformXml/nonMatchingEndTag.xsl");
+
+
runner.enqueue(Paths.get("src/test/resources/TestTransformXml/math.xml"));
+ runner.run();
+
+ runner.assertAllFlowFilesTransferred(TransformXml.REL_FAILURE);
+ MockComponentLog logger = runner.getLogger();
+ assertFalse(logger.getErrorMessages().isEmpty());
+ String firstMessage = logger.getErrorMessages().get(0).getMsg();
+ assertTrue(firstMessage.contains("xsl:template"));
+ }
+
+ @Test
+ public void testMessageTerminate() throws IOException {
+ final TestRunner runner = TestRunners.newTestRunner(new
TransformXml());
+ runner.setProperty("header", "Test message terminate");
+ runner.setProperty(TransformXml.XSLT_FILE_NAME,
"src/test/resources/TestTransformXml/employeeMessageTerminate.xsl");
+
+
runner.enqueue(Paths.get("src/test/resources/TestTransformXml/employee.xml"));
+ runner.run();
+
+ runner.assertAllFlowFilesTransferred(TransformXml.REL_FAILURE);
+ MockComponentLog logger = runner.getLogger();
+ assertFalse(logger.getErrorMessages().isEmpty());
+ String firstMessage = logger.getErrorMessages().get(0).getMsg();
+ assertTrue(firstMessage.contains("xsl:message"));
+ }
+
+ @Test
+ public void testMessageNonTerminate() throws IOException {
+ final TestRunner runner = TestRunners.newTestRunner(new
TransformXml());
+ runner.setProperty("header", "Test message non terminate");
+ runner.setProperty(TransformXml.XSLT_FILE_NAME,
"src/test/resources/TestTransformXml/employeeMessageNonTerminate.xsl");
+
+
runner.enqueue(Paths.get("src/test/resources/TestTransformXml/employee.xml"));
+ runner.run();
+
+ runner.assertAllFlowFilesTransferred(TransformXml.REL_SUCCESS);
+ final MockFlowFile transformed =
runner.getFlowFilesForRelationship(TransformXml.REL_SUCCESS).get(0);
+ final String expectedContent = new
String(Files.readAllBytes(Paths.get("src/test/resources/TestTransformXml/employee.html")));
+
+ transformed.assertContentEquals(expectedContent);
+ MockComponentLog logger = runner.getLogger();
+ assertTrue(logger.getErrorMessages().isEmpty());
+ assertTrue(logger.getWarnMessages().isEmpty());
+ }
}
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employee.html
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employee.html
new file mode 100644
index 0000000000..931b9834f1
--- /dev/null
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employee.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML><html>
+ <body>
+ <h2>Employee</h2>
+ <table border="1">
+ <tr bgcolor="pink">
+ <th>ID</th>
+ <th>First Name</th>
+ <th>Last Name</th>
+ <th>Nick Name</th>
+ <th>Salary</th>
+ </tr>
+ <tr>
+ <td>001</td>
+ <td></td>
+ <td>Gupta</td>
+ <td>Raju</td>
+ <td>30000</td>
+ </tr>
+ <tr>
+ <td>024</td>
+ <td>Sara</td>
+ <td>Khan</td>
+ <td>Zoya</td>
+ <td>25000</td>
+ </tr>
+ <tr>
+ <td>056</td>
+ <td>Peter</td>
+ <td>Symon</td>
+ <td>John</td>
+ <td>10000</td>
+ </tr>
+ </table>
+ </body>
+</html>
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employee.xml
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employee.xml
new file mode 100644
index 0000000000..8b785d3cdd
--- /dev/null
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employee.xml
@@ -0,0 +1,35 @@
+<?xml version = "1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<class>
+ <employee id = "001">
+ <firstname></firstname>
+ <lastname>Gupta</lastname>
+ <nickname>Raju</nickname>
+ <salary>30000</salary>
+ </employee>
+ <employee id = "024">
+ <firstname>Sara</firstname>
+ <lastname>Khan</lastname>
+ <nickname>Zoya</nickname>
+ <salary>25000</salary>
+ </employee>
+ <employee id = "056">
+ <firstname>Peter</firstname>
+ <lastname>Symon</lastname>
+ <nickname>John</nickname>
+ <salary>10000</salary>
+ </employee>
+</class>
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employeeMessageNonTerminate.xsl
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employeeMessageNonTerminate.xsl
new file mode 100644
index 0000000000..01ec5ce61d
--- /dev/null
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employeeMessageNonTerminate.xsl
@@ -0,0 +1,50 @@
+<?xml version = "1.0" encoding = "UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<xsl:stylesheet version = "1.0"
+ xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match = "/">
+ <html>
+ <body>
+ <h2>Employee</h2>
+ <table border = "1">
+ <tr bgcolor = "pink">
+ <th>ID</th>
+ <th>First Name</th>
+ <th>Last Name</th>
+ <th>Nick Name</th>
+ <th>Salary</th>
+ </tr>
+
+ <xsl:for-each select = "class/employee">
+
+ <xsl:if test = "firstname = ''">
+ <xsl:message terminate = "no">A first name field
is empty.
+ </xsl:message>
+ </xsl:if>
+
+ <tr>
+ <td><xsl:value-of select = "@id"/></td>
+ <td><xsl:value-of select = "firstname"/></td>
+ <td><xsl:value-of select = "lastname"/></td>
+ <td><xsl:value-of select = "nickname"/></td>
+ <td><xsl:value-of select = "salary"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employeeMessageTerminate.xsl
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employeeMessageTerminate.xsl
new file mode 100644
index 0000000000..03ea0af03c
--- /dev/null
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/employeeMessageTerminate.xsl
@@ -0,0 +1,50 @@
+<?xml version = "1.0" encoding = "UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<xsl:stylesheet version = "1.0"
+ xmlns:xsl = "http://www.w3.org/1999/XSL/Transform">
+ <xsl:template match = "/">
+ <html>
+ <body>
+ <h2>Employee</h2>
+ <table border = "1">
+ <tr bgcolor = "pink">
+ <th>ID</th>
+ <th>First Name</th>
+ <th>Last Name</th>
+ <th>Nick Name</th>
+ <th>Salary</th>
+ </tr>
+
+ <xsl:for-each select = "class/employee">
+
+ <xsl:if test = "firstname = ''">
+ <xsl:message terminate = "yes">A first name field
is empty.
+ </xsl:message>
+ </xsl:if>
+
+ <tr>
+ <td><xsl:value-of select = "@id"/></td>
+ <td><xsl:value-of select = "firstname"/></td>
+ <td><xsl:value-of select = "lastname"/></td>
+ <td><xsl:value-of select = "nickname"/></td>
+ <td><xsl:value-of select = "salary"/></td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+ </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
diff --git
a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/nonMatchingEndTag.xsl
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/nonMatchingEndTag.xsl
new file mode 100644
index 0000000000..6d2c1533ee
--- /dev/null
+++
b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/resources/TestTransformXml/nonMatchingEndTag.xsl
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<xsl:stylesheet version="2.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+ <xsl:param name="header" />
+
+ <xsl:template match="doc">
+ <HTML>
+ <H1>
+ <xsl:value-of select="$header"/>
+ </H1>
+ <HR/>
+ <P>Should say "1": <xsl:value-of select="5 mod 2"/></P>
+ <P>Should say "1": <xsl:value-of select="n1 mod n2"/></P>
+ <P>Should say "-1": <xsl:value-of select="div mod mod"/></P>
+ <P>
+ <xsl:value-of select="div or ((mod)) | or"/>
+ </P>
+ </HTML>
+</xsl:stylesheet>