Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.marklogic.client.admin.ExtensionMetadata;
import com.marklogic.client.admin.TransformExtensionsManager;
import com.marklogic.client.document.*;
import com.marklogic.client.impl.XmlFactories;
import com.marklogic.client.io.DOMHandle;
import com.marklogic.client.io.FileHandle;
import com.marklogic.client.io.SourceHandle;
Expand Down Expand Up @@ -74,8 +75,7 @@ public void testBulkLoadWithXSLTClientSideTransform() throws KeyManagementExcept
// get the xslt
Source xsl = new StreamSource("src/test/java/com/marklogic/client/functionaltest/data/employee-stylesheet.xsl");

// create transformer
TransformerFactory factory = TransformerFactory.newInstance();
TransformerFactory factory = XmlFactories.makeNewTransformerFactory();
Transformer transformer = factory.newTransformer(xsl);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

import com.marklogic.client.DatabaseClient;
import com.marklogic.client.document.XMLDocumentManager;
import com.marklogic.client.impl.XmlFactories;
import com.marklogic.client.io.BytesHandle;
import com.marklogic.client.io.StringHandle;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
Expand Down Expand Up @@ -50,7 +50,7 @@ public void testEncoding() throws KeyManagementException, NoSuchAlgorithmExcepti

// transform the Document into a String
Source domSource = new DOMSource(doc);
TransformerFactory tf = TransformerFactory.newInstance();
TransformerFactory tf = XmlFactories.makeNewTransformerFactory();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.METHOD, "xml");
transformer.setOutputProperty(OutputKeys.ENCODING, "Cp1252");
Expand Down Expand Up @@ -88,7 +88,7 @@ public void testEncoding() throws KeyManagementException, NoSuchAlgorithmExcepti
x2.appendChild(text2);

Source domSource2 = new DOMSource(doc2);
TransformerFactory tf2 = TransformerFactory.newInstance();
TransformerFactory tf2 = XmlFactories.makeNewTransformerFactory();
Transformer transformer2 = tf2.newTransformer();
transformer2.setOutputProperty(OutputKeys.METHOD, "xml");
transformer2.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@

import com.marklogic.client.DatabaseClient;
import com.marklogic.client.document.XMLDocumentManager;
import com.marklogic.client.impl.XmlFactories;
import com.marklogic.client.io.FileHandle;
import com.marklogic.client.io.SourceHandle;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

import javax.xml.transform.*;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import static org.junit.jupiter.api.Assertions.assertTrue;



public class TestTransformXMLWithXSLT extends AbstractFunctionalTest {
Expand All @@ -31,8 +33,7 @@ public void testWriteXMLWithXSLTransform() throws TransformerException, FileNotF
// get the xslt
Source xsl = new StreamSource("src/test/java/com/marklogic/client/functionaltest/data/employee-stylesheet.xsl");

// create transformer
TransformerFactory factory = TransformerFactory.newInstance();
TransformerFactory factory = XmlFactories.makeNewTransformerFactory();
Transformer transformer = factory.newTransformer(xsl);
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.marklogic.client.DatabaseClient;
import com.marklogic.client.admin.QueryOptionsManager;
import com.marklogic.client.document.DocumentManager;
import com.marklogic.client.impl.XmlFactories;
import com.marklogic.client.io.*;
import com.marklogic.client.io.DocumentMetadataHandle.DocumentCollections;
import com.marklogic.client.io.DocumentMetadataHandle.DocumentPermissions;
Expand Down Expand Up @@ -1476,7 +1477,7 @@ public String convertXMLStreamReaderToString(XMLStreamReader reader) throws XMLS
*/
public String convertXMLDocumentToString(Document readContent) throws TransformerException
{
TransformerFactory tf = TransformerFactory.newInstance();
TransformerFactory tf = XmlFactories.makeNewTransformerFactory();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StringWriter writer = new StringWriter();
Expand Down Expand Up @@ -1514,10 +1515,10 @@ public String convertInputStreamToString(InputStream fileRead) throws IOExceptio
* @throws IOException
* @throws TransformerException
*/
public String convertInputSourceToString(InputSource fileRead) throws IOException, TransformerException
public String convertInputSourceToString(InputSource fileRead) throws TransformerException
{
Source saxsrc = new SAXSource(fileRead);
TransformerFactory tf = TransformerFactory.newInstance();
TransformerFactory tf = XmlFactories.makeNewTransformerFactory();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
StringWriter writer = new StringWriter();
Expand All @@ -1538,7 +1539,7 @@ public String convertSourceToString(Source reader) throws TransformerException
{
StringWriter stringWriter = new StringWriter();
Result result = new StreamResult(stringWriter);
TransformerFactory factory = TransformerFactory.newInstance();
TransformerFactory factory = XmlFactories.makeNewTransformerFactory();
Transformer transformer = factory.newTransformer();
transformer.transform(reader, result);
String str = stringWriter.getBuffer().toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@
*/
package com.marklogic.client.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.XMLConstants;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import java.lang.ref.SoftReference;

public final class XmlFactories {

private static final Logger logger = LoggerFactory.getLogger(XmlFactories.class);

private static final CachedInstancePerThreadSupplier<XMLOutputFactory> cachedOutputFactory =
new CachedInstancePerThreadSupplier<XMLOutputFactory>(new Supplier<XMLOutputFactory>() {
@Override
Expand Down Expand Up @@ -51,13 +55,25 @@ public static XMLInputFactory makeNewInputFactory() {
return factory;
}

public static TransformerFactory makeNewTransformerFactory() throws TransformerConfigurationException {
public static TransformerFactory makeNewTransformerFactory() {
TransformerFactory factory = TransformerFactory.newInstance();
// Avoids Polaris warning related to https://cwe.mitre.org/data/definitions/611.html .
// From https://stackoverflow.com/questions/32178558/how-to-prevent-xml-external-entity-injection-on-transformerfactory .
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
try {
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
} catch (TransformerConfigurationException e) {
logger.warn("Unable to set {} on TransformerFactory; cause: {}", XMLConstants.FEATURE_SECURE_PROCESSING, e.getMessage());
}
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
} catch (IllegalArgumentException e) {
logger.warn("Unable to set {} on TransformerFactory; cause: {}", XMLConstants.ACCESS_EXTERNAL_DTD, e.getMessage());
}
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
} catch (IllegalArgumentException e) {
logger.warn("Unable to set {} on TransformerFactory; cause: {}", XMLConstants.ACCESS_EXTERNAL_STYLESHEET, e.getMessage());
}
return factory;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,24 @@
*/
package com.marklogic.client.io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import com.marklogic.client.MarkLogicIOException;
import com.marklogic.client.MarkLogicInternalException;
import com.marklogic.client.impl.XmlFactories;
import com.marklogic.client.io.marker.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.*;

import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;

import com.marklogic.client.io.marker.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.*;

import com.marklogic.client.MarkLogicIOException;
import com.marklogic.client.MarkLogicInternalException;
import java.io.*;
import java.nio.charset.StandardCharsets;

/**
* <p>An Input Source Handle represents XML content as an input source for reading or writing.
Expand Down Expand Up @@ -413,12 +403,12 @@ protected OutputStreamSender sendContent() {
}
protected OutputStreamSender sendContent(InputSource content) {
return (content == null) ? null :
new OutputStreamSenderImpl(makeTransformer(), makeReader(true), content);
new OutputStreamSenderImpl(makeTransformerFactory(), makeReader(true), content);
}
@Override
public void write(OutputStream out) throws IOException {
try {
makeTransformer().newTransformer().transform(
makeTransformerFactory().newTransformer().transform(
new SAXSource(makeReader(true), content),
new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8))
);
Expand All @@ -427,20 +417,8 @@ public void write(OutputStream out) throws IOException {
throw new MarkLogicIOException(e);
}
}
private TransformerFactory makeTransformer() {
TransformerFactory factory = TransformerFactory.newInstance();
// default to best practices for conservative security including recommendations per
// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md
try {
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
} catch (TransformerConfigurationException e) {}
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
} catch (IllegalArgumentException e) {}
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
} catch (IllegalArgumentException e) {}
return factory;
private TransformerFactory makeTransformerFactory() {
return XmlFactories.makeNewTransformerFactory();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,17 @@
*/
package com.marklogic.client.io;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

import javax.xml.XMLConstants;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import com.marklogic.client.MarkLogicIOException;
import com.marklogic.client.impl.XmlFactories;
import com.marklogic.client.io.marker.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.marklogic.client.MarkLogicIOException;
import javax.xml.transform.*;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.nio.charset.StandardCharsets;

/**
* <p>A Source Handle represents XML content as a transform source for reading
Expand Down Expand Up @@ -177,7 +167,7 @@ public void transform(Result result) {
} else {
if (logger.isWarnEnabled())
logger.warn("No transformer, so using identity transform");
transformer = makeTransformer().newTransformer();
transformer = makeTransformerFactory().newTransformer();
}

transformer.transform(content, result);
Expand All @@ -186,20 +176,8 @@ public void transform(Result result) {
throw new MarkLogicIOException(e);
}
}
private TransformerFactory makeTransformer() {
TransformerFactory factory = TransformerFactory.newInstance();
// default to best practices for conservative security including recommendations per
// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md
try {
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
} catch (TransformerConfigurationException e) {}
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
} catch (IllegalArgumentException e) {}
try {
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
} catch (IllegalArgumentException e) {}
return factory;
private TransformerFactory makeTransformerFactory() {
return XmlFactories.makeNewTransformerFactory();
}

/**
Expand Down Expand Up @@ -260,7 +238,7 @@ public byte[] contentToBytes(Source content) {
if (content == null) return null;
try {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
makeTransformer().newTransformer().transform(content,
makeTransformerFactory().newTransformer().transform(content,
new StreamResult(new OutputStreamWriter(buffer, StandardCharsets.UTF_8)));
return buffer.toByteArray();
} catch (TransformerException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.marklogic.client.document.BinaryDocumentManager;
import com.marklogic.client.document.TextDocumentManager;
import com.marklogic.client.document.XMLDocumentManager;
import com.marklogic.client.impl.XmlFactories;
import com.marklogic.client.io.BaseHandle;
import com.marklogic.client.io.Format;
import com.marklogic.client.io.JAXBHandle;
Expand All @@ -18,6 +19,8 @@
import com.marklogic.client.query.MatchDocumentSummary;
import com.marklogic.client.query.QueryDefinition;
import com.marklogic.client.query.QueryManager;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.annotation.XmlRootElement;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
Expand All @@ -27,16 +30,17 @@
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.annotation.XmlRootElement;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import java.io.*;
Expand Down Expand Up @@ -144,7 +148,7 @@ public void testBuiltinReadWrite()
xmlMgr.delete(xmlDocId);
assertEquals(beforeText, afterText);

Transformer transformer = TransformerFactory.newInstance().newTransformer();
Transformer transformer = XmlFactories.makeNewTransformerFactory().newTransformer();

xmlMgr.writeAs(xmlDocId, new DOMSource(beforeDocument));
DOMResult afterResult = new DOMResult();
Expand Down
Loading