mirror of https://github.com/apache/nifi.git
NIFI-9943 Added Transform Provider to nifi-xml-processing
- Refactored TransformerFactory references using StandardTransformerProvider This closes #5986 Signed-off-by: Paul Grey <greyp@apache.org>
This commit is contained in:
parent
4450f4ce50
commit
b288810316
|
@ -48,17 +48,13 @@ import org.apache.nifi.minifi.commons.schema.serialization.SchemaLoader;
|
|||
import org.apache.nifi.util.NiFiProperties;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -147,20 +143,18 @@ public final class ConfigTransformer {
|
|||
}
|
||||
}
|
||||
|
||||
protected static void writeFlowXmlFile(ConfigSchema configSchema, OutputStream outputStream) throws TransformerException, ConfigTransformerException {
|
||||
protected static void writeFlowXmlFile(ConfigSchema configSchema, OutputStream outputStream) throws ConfigTransformerException {
|
||||
final StreamResult streamResult = new StreamResult(outputStream);
|
||||
|
||||
// configure the transformer and convert the DOM
|
||||
final TransformerFactory transformFactory = TransformerFactory.newInstance();
|
||||
final Transformer transformer = transformFactory.newTransformer();
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
final StandardTransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.setIndent(true);
|
||||
|
||||
// transform the document to byte stream
|
||||
transformer.transform(createFlowXml(configSchema), streamResult);
|
||||
transformProvider.transform(createFlowXml(configSchema), streamResult);
|
||||
}
|
||||
|
||||
protected static void writeFlowXmlFile(ConfigSchema configSchema, String path) throws IOException, TransformerException, ConfigurationChangeException, ConfigTransformerException {
|
||||
protected static void writeFlowXmlFile(ConfigSchema configSchema, String path) throws IOException, ConfigTransformerException {
|
||||
try (OutputStream fileOut = Files.newOutputStream(Paths.get(path, "flow.xml.gz"))) {
|
||||
try (OutputStream outStream = new GZIPOutputStream(fileOut)) {
|
||||
writeFlowXmlFile(configSchema, outStream);
|
||||
|
@ -362,7 +356,7 @@ public final class ConfigTransformer {
|
|||
}
|
||||
|
||||
return new DOMSource(doc);
|
||||
} catch (final ProcessingException | DOMException | TransformerFactoryConfigurationError | IllegalArgumentException e) {
|
||||
} catch (final ProcessingException | DOMException | IllegalArgumentException e) {
|
||||
throw new ConfigTransformerException(e);
|
||||
} catch (Exception e) {
|
||||
throw new ConfigTransformerException("Failed to parse the config YAML while writing the top level of the flow xml", e);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.nifi.xml.processing;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
|
||||
/**
|
||||
* XML Processing Attributes
|
||||
*/
|
||||
public enum ProcessingAttribute {
|
||||
/** Access External Document Type Declaration with an empty string to deny all access to external references */
|
||||
ACCESS_EXTERNAL_DTD(XMLConstants.ACCESS_EXTERNAL_DTD, ""),
|
||||
|
||||
/** Access External Stylesheet with an empty string to deny all access to external references */
|
||||
ACCESS_EXTERNAL_STYLESHEET(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
|
||||
|
||||
private final String attribute;
|
||||
|
||||
private final Object value;
|
||||
|
||||
ProcessingAttribute(final String attribute, final Object value) {
|
||||
this.attribute = attribute;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.nifi.xml.processing.transform;
|
||||
|
||||
import org.apache.nifi.xml.processing.ProcessingAttribute;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Standard implementation of Transform Provider with secure processing enabled
|
||||
*/
|
||||
public class StandardTransformProvider implements TransformProvider {
|
||||
private static final boolean SECURE_PROCESSING_ENABLED = true;
|
||||
|
||||
private static final String ENABLED_PROPERTY = "yes";
|
||||
|
||||
private static final String INDENT_AMOUNT_OUTPUT_KEY = "{http://xml.apache.org/xslt}indent-amount";
|
||||
|
||||
private static final String INDENT_AMOUNT = "2";
|
||||
|
||||
private boolean indent;
|
||||
|
||||
private boolean omitXmlDeclaration;
|
||||
|
||||
private String method;
|
||||
|
||||
/**
|
||||
* Set Indent Status
|
||||
*
|
||||
* @param indent Indent Status
|
||||
*/
|
||||
public void setIndent(final boolean indent) {
|
||||
this.indent = indent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Output Method
|
||||
*
|
||||
* @param method Method or null when default configuration should be used
|
||||
*/
|
||||
public void setMethod(final String method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Omit XML Declaration
|
||||
*
|
||||
* @param omitXmlDeclaration Omit XML Declaration
|
||||
*/
|
||||
public void setOmitXmlDeclaration(final boolean omitXmlDeclaration) {
|
||||
this.omitXmlDeclaration = omitXmlDeclaration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform Source to Result
|
||||
*
|
||||
* @param source Source to be transformed
|
||||
* @param result Result containing transformed information
|
||||
*/
|
||||
@Override
|
||||
public void transform(final Source source, final Result result) {
|
||||
Objects.requireNonNull(source, "Source required");
|
||||
Objects.requireNonNull(result, "Result required");
|
||||
|
||||
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
final Transformer transformer;
|
||||
try {
|
||||
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ProcessingAttribute.ACCESS_EXTERNAL_DTD.getValue());
|
||||
transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ProcessingAttribute.ACCESS_EXTERNAL_STYLESHEET.getValue());
|
||||
transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, SECURE_PROCESSING_ENABLED);
|
||||
transformer = transformerFactory.newTransformer();
|
||||
} catch (final TransformerConfigurationException e) {
|
||||
throw new ProcessingException("Transformer configuration failed", e);
|
||||
}
|
||||
|
||||
if (indent) {
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, ENABLED_PROPERTY);
|
||||
transformer.setOutputProperty(INDENT_AMOUNT_OUTPUT_KEY, INDENT_AMOUNT);
|
||||
}
|
||||
|
||||
if (method != null) {
|
||||
transformer.setOutputProperty(OutputKeys.METHOD, method);
|
||||
}
|
||||
|
||||
if (omitXmlDeclaration) {
|
||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, ENABLED_PROPERTY);
|
||||
}
|
||||
|
||||
try {
|
||||
transformer.transform(source, result);
|
||||
} catch (final TransformerException e) {
|
||||
throw new ProcessingException("Transform failed", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.nifi.xml.processing.transform;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
/**
|
||||
* XML Transformation Provider
|
||||
*/
|
||||
public interface TransformProvider {
|
||||
/**
|
||||
* Transform Source to Result
|
||||
*
|
||||
* @param source Source to be transformed
|
||||
* @param result Result containing transformed information
|
||||
*/
|
||||
void transform(Source source, Result result);
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.apache.nifi.xml.processing.transform;
|
||||
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.ResourceProvider;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class StandardTransformProviderTest {
|
||||
private static final String METHOD = "xml";
|
||||
|
||||
@Test
|
||||
void testTransformStandard() throws IOException {
|
||||
final StandardTransformProvider provider = new StandardTransformProvider();
|
||||
|
||||
final DOMResult result = new DOMResult();
|
||||
|
||||
try (final InputStream inputStream = ResourceProvider.getStandardDocument()) {
|
||||
final Source source = new StreamSource(inputStream);
|
||||
provider.transform(source, result);
|
||||
}
|
||||
|
||||
assertDocumentNodeFound(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransformStandardDocumentTypeDeclaration() throws IOException {
|
||||
final StandardTransformProvider provider = new StandardTransformProvider();
|
||||
provider.setIndent(true);
|
||||
provider.setOmitXmlDeclaration(true);
|
||||
provider.setMethod(METHOD);
|
||||
|
||||
final DOMResult result = new DOMResult();
|
||||
|
||||
try (final InputStream inputStream = ResourceProvider.getStandardDocumentDocType()) {
|
||||
final Source source = new StreamSource(inputStream);
|
||||
provider.transform(source, result);
|
||||
}
|
||||
|
||||
assertDocumentNodeFound(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTransformStandardExternalEntityException() throws IOException {
|
||||
final StandardTransformProvider provider = new StandardTransformProvider();
|
||||
|
||||
final DOMResult result = new DOMResult();
|
||||
|
||||
try (final InputStream inputStream = ResourceProvider.getStandardDocumentDocTypeEntity()) {
|
||||
final Source source = new StreamSource(inputStream);
|
||||
final ProcessingException processingException = assertThrows(ProcessingException.class, () -> provider.transform(source, result));
|
||||
assertInstanceOf(TransformerException.class, processingException.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
private void assertDocumentNodeFound(final DOMResult result) {
|
||||
final Node node = result.getNode();
|
||||
assertNotNull(node);
|
||||
assertEquals(Node.DOCUMENT_NODE, node.getNodeType());
|
||||
}
|
||||
}
|
|
@ -32,10 +32,10 @@ import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
|
|||
import org.apache.nifi.web.api.dto.RelationshipDTO;
|
||||
import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
|
||||
import org.apache.nifi.web.api.dto.TemplateDTO;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.apache.nifi.xml.processing.transform.TransformProvider;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -58,9 +58,8 @@ public class TemplateUtils {
|
|||
|
||||
// need to stream the template element as the TemplateDeserializer.deserialize operation needs to re-parse
|
||||
// in order to apply explicit properties on the XMLInputFactory
|
||||
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
final Transformer transformer = transformerFactory.newTransformer();
|
||||
transformer.transform(domSource, streamResult);
|
||||
final TransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.transform(domSource, streamResult);
|
||||
|
||||
return parseDto(baos.toByteArray());
|
||||
} catch (final Exception e) {
|
||||
|
|
|
@ -52,16 +52,12 @@ import org.apache.nifi.util.CharacterFilterUtils;
|
|||
import org.apache.nifi.util.StringUtils;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.w3c.dom.DOMException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.BufferedOutputStream;
|
||||
|
@ -127,7 +123,7 @@ public class StandardFlowSerializer implements FlowSerializer<Document> {
|
|||
}
|
||||
|
||||
return doc;
|
||||
} catch (final ProcessingException | DOMException | TransformerFactoryConfigurationError | IllegalArgumentException e) {
|
||||
} catch (final ProcessingException | DOMException | IllegalArgumentException e) {
|
||||
throw new FlowSerializationException(e);
|
||||
}
|
||||
}
|
||||
|
@ -139,15 +135,13 @@ public class StandardFlowSerializer implements FlowSerializer<Document> {
|
|||
final StreamResult streamResult = new StreamResult(new BufferedOutputStream(os));
|
||||
|
||||
// configure the transformer and convert the DOM
|
||||
final TransformerFactory transformFactory = TransformerFactory.newInstance();
|
||||
final Transformer transformer = transformFactory.newTransformer();
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
final StandardTransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.setIndent(true);
|
||||
|
||||
// transform the document to byte stream
|
||||
transformer.transform(domSource, streamResult);
|
||||
transformProvider.transform(domSource, streamResult);
|
||||
|
||||
} catch (final DOMException | TransformerFactoryConfigurationError | IllegalArgumentException | TransformerException e) {
|
||||
} catch (final DOMException | IllegalArgumentException | ProcessingException e) {
|
||||
throw new FlowSerializationException(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ import org.apache.nifi.web.api.dto.PortDTO;
|
|||
import org.apache.nifi.web.api.dto.PositionDTO;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.apache.nifi.xml.processing.transform.TransformProvider;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.w3c.dom.Document;
|
||||
|
@ -40,8 +42,6 @@ import javax.xml.XMLConstants;
|
|||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.validation.Schema;
|
||||
|
@ -278,13 +278,14 @@ public class FlowParser {
|
|||
* @param flowDocument flowDocument of the associated XML content to write to disk
|
||||
* @param flowXmlPath path on disk to write the flow
|
||||
* @throws IOException if there are issues in accessing the target destination for the flow
|
||||
* @throws TransformerException if there are issues in the xml transformation process
|
||||
*/
|
||||
public void writeFlow(final Document flowDocument, final Path flowXmlPath) throws IOException, TransformerException {
|
||||
public void writeFlow(final Document flowDocument, final Path flowXmlPath) throws IOException {
|
||||
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
final Source xmlSource = new DOMSource(flowDocument);
|
||||
final Result outputTarget = new StreamResult(outputStream);
|
||||
TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
|
||||
|
||||
final TransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.transform(xmlSource, outputTarget);
|
||||
final InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
|
||||
|
||||
try (final OutputStream output = Files.newOutputStream(flowXmlPath, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
|
||||
|
|
|
@ -23,9 +23,6 @@ import java.io.IOException;
|
|||
import java.io.StringWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
@ -45,6 +42,8 @@ import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
|
|||
import org.apache.nifi.authorization.exception.UninheritableAuthorizationsException;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.apache.nifi.xml.processing.transform.TransformProvider;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
@ -142,9 +141,9 @@ public class ManagedRangerAuthorizer extends RangerNiFiAuthorizer implements Man
|
|||
userGroupProviderElement.appendChild(document.createTextNode(((ConfigurableUserGroupProvider) userGroupProvider).getFingerprint()));
|
||||
}
|
||||
|
||||
final Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
transformer.transform(new DOMSource(document), new StreamResult(out));
|
||||
} catch (final ProcessingException | TransformerException e) {
|
||||
final TransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.transform(new DOMSource(document), new StreamResult(out));
|
||||
} catch (final ProcessingException e) {
|
||||
throw new AuthorizationAccessException("Unable to generate fingerprint", e);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
<version>1.17.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.nifi</groupId>
|
||||
<artifactId>nifi-xml-processing</artifactId>
|
||||
<version>1.17.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
|
|
|
@ -25,6 +25,8 @@ import org.apache.avro.generic.GenericData;
|
|||
import org.apache.avro.generic.GenericDatumReader;
|
||||
import org.apache.avro.io.DatumReader;
|
||||
import org.apache.nifi.web.ViewableContent.DisplayMode;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.LocalTime;
|
||||
|
@ -33,11 +35,6 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.IOException;
|
||||
|
@ -94,13 +91,11 @@ public class StandardContentViewerController extends HttpServlet {
|
|||
final StreamSource source = new StreamSource(content.getContentStream());
|
||||
final StreamResult result = new StreamResult(writer);
|
||||
|
||||
final TransformerFactory transformFactory = TransformerFactory.newInstance();
|
||||
final Transformer transformer = transformFactory.newTransformer();
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
final StandardTransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.setIndent(true);
|
||||
|
||||
transformer.transform(source, result);
|
||||
} catch (final TransformerFactoryConfigurationError | TransformerException te) {
|
||||
transformProvider.transform(source, result);
|
||||
} catch (final ProcessingException te) {
|
||||
throw new IOException("Unable to transform content as XML: " + te, te);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,18 +32,11 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.ErrorListener;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.xpath.XPathExpression;
|
||||
|
@ -77,7 +70,9 @@ import org.apache.nifi.processor.ProcessorInitializationContext;
|
|||
import org.apache.nifi.processor.Relationship;
|
||||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processors.standard.xml.DocumentTypeAllowedDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import net.sf.saxon.xpath.XPathEvaluator;
|
||||
|
@ -278,6 +273,8 @@ public class EvaluateXPath extends AbstractProcessor {
|
|||
|
||||
final boolean validatingDeclaration = context.getProperty(VALIDATE_DTD).asBoolean();
|
||||
|
||||
final StandardTransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.setIndent(true);
|
||||
flowFileLoop:
|
||||
for (FlowFile flowFile : flowFiles) {
|
||||
final AtomicReference<Throwable> error = new AtomicReference<>(null);
|
||||
|
@ -331,17 +328,19 @@ public class EvaluateXPath extends AbstractProcessor {
|
|||
if (DESTINATION_ATTRIBUTE.equals(destination)) {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
doTransform(sourceNode, baos);
|
||||
final StreamResult streamResult = new StreamResult(baos);
|
||||
transformProvider.transform(sourceNode, streamResult);
|
||||
xpathResults.put(entry.getKey(), new String(baos.toByteArray(), StandardCharsets.UTF_8));
|
||||
} catch (TransformerException e) {
|
||||
} catch (final ProcessingException e) {
|
||||
error.set(e);
|
||||
}
|
||||
|
||||
} else if (DESTINATION_CONTENT.equals(destination)) {
|
||||
flowFile = session.write(flowFile, rawOut -> {
|
||||
try (final OutputStream out = new BufferedOutputStream(rawOut)) {
|
||||
doTransform(sourceNode, out);
|
||||
} catch (TransformerException e) {
|
||||
final StreamResult streamResult = new StreamResult(out);
|
||||
transformProvider.transform(sourceNode, streamResult);
|
||||
} catch (final ProcessingException e) {
|
||||
error.set(e);
|
||||
}
|
||||
});
|
||||
|
@ -381,48 +380,6 @@ public class EvaluateXPath extends AbstractProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
private void doTransform(final Source sourceNode, OutputStream out) throws TransformerFactoryConfigurationError, TransformerException {
|
||||
final Transformer transformer;
|
||||
try {
|
||||
transformer = TransformerFactory.newInstance().newTransformer();
|
||||
} catch (final Exception e) {
|
||||
throw new ProcessException(e);
|
||||
}
|
||||
|
||||
final Properties props = new Properties();
|
||||
props.setProperty(OutputKeys.METHOD, "xml");
|
||||
props.setProperty(OutputKeys.INDENT, "no");
|
||||
props.setProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
|
||||
transformer.setOutputProperties(props);
|
||||
|
||||
final ComponentLog logger = getLogger();
|
||||
|
||||
final AtomicReference<TransformerException> error = new AtomicReference<>(null);
|
||||
transformer.setErrorListener(new ErrorListener() {
|
||||
@Override
|
||||
public void warning(final TransformerException exception) {
|
||||
logger.warn("Encountered warning from XPath Engine", exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(final TransformerException exception) {
|
||||
logger.error("Encountered error from XPath Engine", exception);
|
||||
error.set(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(final TransformerException exception) {
|
||||
logger.error("Encountered warning from XPath Engine", exception);
|
||||
error.set(exception);
|
||||
}
|
||||
});
|
||||
|
||||
transformer.transform(sourceNode, new StreamResult(out));
|
||||
if (error.get() != null) {
|
||||
throw error.get();
|
||||
}
|
||||
}
|
||||
|
||||
private static class XPathValidator implements Validator {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,14 +30,8 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.TransformerFactoryConfigurationError;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import net.sf.saxon.s9api.Processor;
|
||||
|
@ -75,7 +69,9 @@ import org.apache.nifi.processor.Relationship;
|
|||
import org.apache.nifi.processor.exception.ProcessException;
|
||||
import org.apache.nifi.processor.util.StandardValidators;
|
||||
import org.apache.nifi.processors.standard.xml.DocumentTypeAllowedDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
@EventDriven
|
||||
|
@ -315,9 +311,9 @@ public class EvaluateXQuery extends AbstractProcessor {
|
|||
final XdmItem item = result.itemAt(0);
|
||||
flowFile = session.write(flowFile, rawOut -> {
|
||||
try (final OutputStream out = new BufferedOutputStream(rawOut)) {
|
||||
writeformattedItem(item, context, out);
|
||||
} catch (TransformerFactoryConfigurationError | TransformerException e) {
|
||||
throw new IOException(e);
|
||||
writeFormattedItem(item, context, out);
|
||||
} catch (final ProcessingException e) {
|
||||
throw new IOException("Writing Formatted Output failed", e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
@ -326,9 +322,9 @@ public class EvaluateXQuery extends AbstractProcessor {
|
|||
ff = session.write(ff, rawOut -> {
|
||||
try (final OutputStream out = new BufferedOutputStream(rawOut)) {
|
||||
try {
|
||||
writeformattedItem(item, context, out);
|
||||
} catch (TransformerFactoryConfigurationError | TransformerException e) {
|
||||
throw new IOException(e);
|
||||
writeFormattedItem(item, context, out);
|
||||
} catch (final ProcessingException e) {
|
||||
throw new IOException("Writing Formatted Output failed", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -341,7 +337,7 @@ public class EvaluateXQuery extends AbstractProcessor {
|
|||
session.transfer(flowFile, REL_FAILURE);
|
||||
session.remove(childrenFlowFiles);
|
||||
continue flowFileLoop;
|
||||
} catch (TransformerFactoryConfigurationError | TransformerException | IOException e) {
|
||||
} catch (final IOException e) {
|
||||
logger.error("XQuery Property [{}] configuration failed", entry.getKey(), e);
|
||||
session.transfer(flowFile, REL_FAILURE);
|
||||
session.remove(childrenFlowFiles);
|
||||
|
@ -369,14 +365,13 @@ public class EvaluateXQuery extends AbstractProcessor {
|
|||
} // end flowFileLoop
|
||||
}
|
||||
|
||||
private String formatItem(XdmItem item, ProcessContext context) throws TransformerFactoryConfigurationError, TransformerException, IOException {
|
||||
private String formatItem(XdmItem item, ProcessContext context) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
writeformattedItem(item, context, baos);
|
||||
writeFormattedItem(item, context, baos);
|
||||
return baos.toString();
|
||||
}
|
||||
|
||||
void writeformattedItem(XdmItem item, ProcessContext context, OutputStream out)
|
||||
throws TransformerFactoryConfigurationError, TransformerException, IOException {
|
||||
void writeFormattedItem(XdmItem item, ProcessContext context, OutputStream out) throws IOException {
|
||||
|
||||
if (item.isAtomicValue()) {
|
||||
out.write(item.getStringValue().getBytes(StandardCharsets.UTF_8));
|
||||
|
@ -385,10 +380,18 @@ public class EvaluateXQuery extends AbstractProcessor {
|
|||
switch (node.getNodeKind()) {
|
||||
case DOCUMENT:
|
||||
case ELEMENT:
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
final Properties props = getTransformerProperties(context);
|
||||
transformer.setOutputProperties(props);
|
||||
transformer.transform(node.asSource(), new StreamResult(out));
|
||||
final StandardTransformProvider transformProvider = new StandardTransformProvider();
|
||||
final String method = context.getProperty(XML_OUTPUT_METHOD).getValue();
|
||||
transformProvider.setMethod(method);
|
||||
|
||||
final boolean indentEnabled = context.getProperty(XML_OUTPUT_INDENT).asBoolean();
|
||||
transformProvider.setIndent(indentEnabled);
|
||||
|
||||
final boolean omitXmlDeclaration = context.getProperty(XML_OUTPUT_OMIT_XML_DECLARATION).asBoolean();
|
||||
transformProvider.setOmitXmlDeclaration(omitXmlDeclaration);
|
||||
|
||||
final StreamResult result = new StreamResult(out);
|
||||
transformProvider.transform(node.asSource(), result);
|
||||
break;
|
||||
default:
|
||||
out.write(node.getStringValue().getBytes(StandardCharsets.UTF_8));
|
||||
|
@ -396,21 +399,6 @@ public class EvaluateXQuery extends AbstractProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
private Properties getTransformerProperties(ProcessContext context) {
|
||||
final String method = context.getProperty(XML_OUTPUT_METHOD).getValue();
|
||||
boolean indent = context.getProperty(XML_OUTPUT_INDENT).asBoolean();
|
||||
boolean omitDeclaration = context.getProperty(XML_OUTPUT_OMIT_XML_DECLARATION).asBoolean();
|
||||
return getTransformerProperties(method, indent, omitDeclaration);
|
||||
}
|
||||
|
||||
static Properties getTransformerProperties(final String method, final boolean indent, final boolean omitDeclaration) {
|
||||
final Properties props = new Properties();
|
||||
props.setProperty(OutputKeys.METHOD, method);
|
||||
props.setProperty(OutputKeys.INDENT, indent ? "yes" : "no");
|
||||
props.setProperty(OutputKeys.OMIT_XML_DECLARATION, omitDeclaration ? "yes" : "no");
|
||||
return props;
|
||||
}
|
||||
|
||||
private static class XQueryValidator implements Validator {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -32,9 +32,6 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.xml.transform.OutputKeys;
|
||||
|
||||
import org.apache.nifi.util.MockFlowFile;
|
||||
import org.apache.nifi.util.TestRunner;
|
||||
|
@ -53,21 +50,6 @@ public class TestEvaluateXQuery {
|
|||
private static final String[] methods = {EvaluateXQuery.OUTPUT_METHOD_XML, EvaluateXQuery.OUTPUT_METHOD_HTML, EvaluateXQuery.OUTPUT_METHOD_TEXT};
|
||||
private static final boolean[] booleans = {true, false};
|
||||
|
||||
@Test
|
||||
public void testSetTransformerProperties() {
|
||||
for (final String method : methods) {
|
||||
for (final boolean indent : booleans) {
|
||||
for (final boolean omitDeclaration : booleans) {
|
||||
Properties props = EvaluateXQuery.getTransformerProperties(method, indent, omitDeclaration);
|
||||
assertEquals(3, props.size());
|
||||
assertEquals(method, props.getProperty(OutputKeys.METHOD));
|
||||
assertEquals(indent ? "yes" : "no", props.getProperty(OutputKeys.INDENT));
|
||||
assertEquals(omitDeclaration ? "yes" : "no", props.getProperty(OutputKeys.OMIT_XML_DECLARATION));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatting() throws Exception {
|
||||
|
||||
|
|
|
@ -42,6 +42,8 @@ import org.apache.nifi.registry.util.PropertyValue;
|
|||
import org.apache.nifi.xml.processing.ProcessingException;
|
||||
import org.apache.nifi.xml.processing.parsers.DocumentProvider;
|
||||
import org.apache.nifi.xml.processing.parsers.StandardDocumentProvider;
|
||||
import org.apache.nifi.xml.processing.transform.StandardTransformProvider;
|
||||
import org.apache.nifi.xml.processing.transform.TransformProvider;
|
||||
import org.apache.ranger.audit.model.AuthzAuditEvent;
|
||||
import org.apache.ranger.authorization.hadoop.config.RangerConfiguration;
|
||||
import org.apache.ranger.authorization.hadoop.config.RangerPluginConfig;
|
||||
|
@ -56,9 +58,6 @@ import org.w3c.dom.Element;
|
|||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
@ -339,9 +338,9 @@ public class RangerAuthorizer implements ManagedAuthorizer, AuthorizationAuditor
|
|||
userGroupProviderElement.appendChild(document.createTextNode(((ConfigurableUserGroupProvider) userGroupProvider).getFingerprint()));
|
||||
}
|
||||
|
||||
final Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
transformer.transform(new DOMSource(document), new StreamResult(out));
|
||||
} catch (final ProcessingException | TransformerException e) {
|
||||
final TransformProvider transformProvider = new StandardTransformProvider();
|
||||
transformProvider.transform(new DOMSource(document), new StreamResult(out));
|
||||
} catch (final ProcessingException e) {
|
||||
throw new AuthorizationAccessException("Unable to generate fingerprint", e);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue