Skip to content

Commit 5c9112e

Browse files
authored
Merge pull request #1787 from marklogic/feature/21420-tfactory
MLE-21420 Refactor: Consolidated TransformerFactory construction
2 parents 9bf534b + 2905c8b commit 5c9112e

File tree

10 files changed

+73
-94
lines changed

10 files changed

+73
-94
lines changed

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestBulkWriteWithTransformations.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.marklogic.client.admin.ExtensionMetadata;
99
import com.marklogic.client.admin.TransformExtensionsManager;
1010
import com.marklogic.client.document.*;
11+
import com.marklogic.client.impl.XmlFactories;
1112
import com.marklogic.client.io.DOMHandle;
1213
import com.marklogic.client.io.FileHandle;
1314
import com.marklogic.client.io.SourceHandle;
@@ -74,8 +75,7 @@ public void testBulkLoadWithXSLTClientSideTransform() throws KeyManagementExcept
7475
// get the xslt
7576
Source xsl = new StreamSource("src/test/java/com/marklogic/client/functionaltest/data/employee-stylesheet.xsl");
7677

77-
// create transformer
78-
TransformerFactory factory = TransformerFactory.newInstance();
78+
TransformerFactory factory = XmlFactories.makeNewTransformerFactory();
7979
Transformer transformer = factory.newTransformer(xsl);
8080
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
8181

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestDocumentEncoding.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
import com.marklogic.client.DatabaseClient;
88
import com.marklogic.client.document.XMLDocumentManager;
9+
import com.marklogic.client.impl.XmlFactories;
910
import com.marklogic.client.io.BytesHandle;
1011
import com.marklogic.client.io.StringHandle;
11-
import org.junit.jupiter.api.*;
12-
import static org.junit.jupiter.api.Assertions.*;
12+
import org.junit.jupiter.api.Test;
1313
import org.w3c.dom.DOMImplementation;
1414
import org.w3c.dom.Document;
1515
import org.w3c.dom.Element;
@@ -50,7 +50,7 @@ public void testEncoding() throws KeyManagementException, NoSuchAlgorithmExcepti
5050

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

9090
Source domSource2 = new DOMSource(doc2);
91-
TransformerFactory tf2 = TransformerFactory.newInstance();
91+
TransformerFactory tf2 = XmlFactories.makeNewTransformerFactory();
9292
Transformer transformer2 = tf2.newTransformer();
9393
transformer2.setOutputProperty(OutputKeys.METHOD, "xml");
9494
transformer2.setOutputProperty(OutputKeys.ENCODING, "UTF-8");

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/fastfunctest/TestTransformXMLWithXSLT.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,19 @@
66

77
import com.marklogic.client.DatabaseClient;
88
import com.marklogic.client.document.XMLDocumentManager;
9+
import com.marklogic.client.impl.XmlFactories;
910
import com.marklogic.client.io.FileHandle;
1011
import com.marklogic.client.io.SourceHandle;
11-
import org.junit.jupiter.api.*;
12-
import static org.junit.jupiter.api.Assertions.*;
12+
import org.junit.jupiter.api.Test;
1313

1414
import javax.xml.transform.*;
1515
import javax.xml.transform.stream.StreamSource;
1616
import java.io.File;
1717
import java.io.FileNotFoundException;
1818
import java.util.Scanner;
1919

20+
import static org.junit.jupiter.api.Assertions.assertTrue;
21+
2022

2123

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

34-
// create transformer
35-
TransformerFactory factory = TransformerFactory.newInstance();
36+
TransformerFactory factory = XmlFactories.makeNewTransformerFactory();
3637
Transformer transformer = factory.newTransformer(xsl);
3738
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
3839

marklogic-client-api-functionaltests/src/test/java/com/marklogic/client/functionaltest/BasicJavaClientREST.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.marklogic.client.DatabaseClient;
1515
import com.marklogic.client.admin.QueryOptionsManager;
1616
import com.marklogic.client.document.DocumentManager;
17+
import com.marklogic.client.impl.XmlFactories;
1718
import com.marklogic.client.io.*;
1819
import com.marklogic.client.io.DocumentMetadataHandle.DocumentCollections;
1920
import com.marklogic.client.io.DocumentMetadataHandle.DocumentPermissions;
@@ -1476,7 +1477,7 @@ public String convertXMLStreamReaderToString(XMLStreamReader reader) throws XMLS
14761477
*/
14771478
public String convertXMLDocumentToString(Document readContent) throws TransformerException
14781479
{
1479-
TransformerFactory tf = TransformerFactory.newInstance();
1480+
TransformerFactory tf = XmlFactories.makeNewTransformerFactory();
14801481
Transformer transformer = tf.newTransformer();
14811482
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
14821483
StringWriter writer = new StringWriter();
@@ -1514,10 +1515,10 @@ public String convertInputStreamToString(InputStream fileRead) throws IOExceptio
15141515
* @throws IOException
15151516
* @throws TransformerException
15161517
*/
1517-
public String convertInputSourceToString(InputSource fileRead) throws IOException, TransformerException
1518+
public String convertInputSourceToString(InputSource fileRead) throws TransformerException
15181519
{
15191520
Source saxsrc = new SAXSource(fileRead);
1520-
TransformerFactory tf = TransformerFactory.newInstance();
1521+
TransformerFactory tf = XmlFactories.makeNewTransformerFactory();
15211522
Transformer transformer = tf.newTransformer();
15221523
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
15231524
StringWriter writer = new StringWriter();
@@ -1538,7 +1539,7 @@ public String convertSourceToString(Source reader) throws TransformerException
15381539
{
15391540
StringWriter stringWriter = new StringWriter();
15401541
Result result = new StreamResult(stringWriter);
1541-
TransformerFactory factory = TransformerFactory.newInstance();
1542+
TransformerFactory factory = XmlFactories.makeNewTransformerFactory();
15421543
Transformer transformer = factory.newTransformer();
15431544
transformer.transform(reader, result);
15441545
String str = stringWriter.getBuffer().toString();

marklogic-client-api/src/main/java/com/marklogic/client/impl/XmlFactories.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33
*/
44
package com.marklogic.client.impl;
55

6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
69
import javax.xml.XMLConstants;
710
import javax.xml.stream.FactoryConfigurationError;
811
import javax.xml.stream.XMLInputFactory;
912
import javax.xml.stream.XMLOutputFactory;
1013
import javax.xml.transform.TransformerConfigurationException;
1114
import javax.xml.transform.TransformerFactory;
12-
import javax.xml.transform.TransformerFactoryConfigurationError;
1315
import java.lang.ref.SoftReference;
1416

1517
public final class XmlFactories {
1618

19+
private static final Logger logger = LoggerFactory.getLogger(XmlFactories.class);
20+
1721
private static final CachedInstancePerThreadSupplier<XMLOutputFactory> cachedOutputFactory =
1822
new CachedInstancePerThreadSupplier<XMLOutputFactory>(new Supplier<XMLOutputFactory>() {
1923
@Override
@@ -51,13 +55,25 @@ public static XMLInputFactory makeNewInputFactory() {
5155
return factory;
5256
}
5357

54-
public static TransformerFactory makeNewTransformerFactory() throws TransformerConfigurationException {
58+
public static TransformerFactory makeNewTransformerFactory() {
5559
TransformerFactory factory = TransformerFactory.newInstance();
5660
// Avoids Polaris warning related to https://cwe.mitre.org/data/definitions/611.html .
5761
// From https://stackoverflow.com/questions/32178558/how-to-prevent-xml-external-entity-injection-on-transformerfactory .
58-
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
59-
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
60-
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
62+
try {
63+
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
64+
} catch (TransformerConfigurationException e) {
65+
logger.warn("Unable to set {} on TransformerFactory; cause: {}", XMLConstants.FEATURE_SECURE_PROCESSING, e.getMessage());
66+
}
67+
try {
68+
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
69+
} catch (IllegalArgumentException e) {
70+
logger.warn("Unable to set {} on TransformerFactory; cause: {}", XMLConstants.ACCESS_EXTERNAL_DTD, e.getMessage());
71+
}
72+
try {
73+
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
74+
} catch (IllegalArgumentException e) {
75+
logger.warn("Unable to set {} on TransformerFactory; cause: {}", XMLConstants.ACCESS_EXTERNAL_STYLESHEET, e.getMessage());
76+
}
6177
return factory;
6278
}
6379

marklogic-client-api/src/main/java/com/marklogic/client/io/InputSourceHandle.java

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,24 @@
33
*/
44
package com.marklogic.client.io;
55

6-
import java.io.ByteArrayInputStream;
7-
import java.io.ByteArrayOutputStream;
8-
import java.io.Closeable;
9-
import java.io.IOException;
10-
import java.io.InputStream;
11-
import java.io.InputStreamReader;
12-
import java.io.OutputStream;
13-
import java.io.OutputStreamWriter;
14-
import java.io.UnsupportedEncodingException;
15-
import java.nio.charset.StandardCharsets;
6+
import com.marklogic.client.MarkLogicIOException;
7+
import com.marklogic.client.MarkLogicInternalException;
8+
import com.marklogic.client.impl.XmlFactories;
9+
import com.marklogic.client.io.marker.*;
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
import org.xml.sax.*;
1613

1714
import javax.xml.XMLConstants;
1815
import javax.xml.parsers.ParserConfigurationException;
1916
import javax.xml.parsers.SAXParserFactory;
20-
import javax.xml.transform.TransformerConfigurationException;
2117
import javax.xml.transform.TransformerException;
2218
import javax.xml.transform.TransformerFactory;
2319
import javax.xml.transform.sax.SAXSource;
2420
import javax.xml.transform.stream.StreamResult;
2521
import javax.xml.validation.Schema;
26-
27-
import com.marklogic.client.io.marker.*;
28-
import org.slf4j.Logger;
29-
import org.slf4j.LoggerFactory;
30-
import org.xml.sax.*;
31-
32-
import com.marklogic.client.MarkLogicIOException;
33-
import com.marklogic.client.MarkLogicInternalException;
22+
import java.io.*;
23+
import java.nio.charset.StandardCharsets;
3424

3525
/**
3626
* <p>An Input Source Handle represents XML content as an input source for reading or writing.
@@ -413,12 +403,12 @@ protected OutputStreamSender sendContent() {
413403
}
414404
protected OutputStreamSender sendContent(InputSource content) {
415405
return (content == null) ? null :
416-
new OutputStreamSenderImpl(makeTransformer(), makeReader(true), content);
406+
new OutputStreamSenderImpl(makeTransformerFactory(), makeReader(true), content);
417407
}
418408
@Override
419409
public void write(OutputStream out) throws IOException {
420410
try {
421-
makeTransformer().newTransformer().transform(
411+
makeTransformerFactory().newTransformer().transform(
422412
new SAXSource(makeReader(true), content),
423413
new StreamResult(new OutputStreamWriter(out, StandardCharsets.UTF_8))
424414
);
@@ -427,20 +417,8 @@ public void write(OutputStream out) throws IOException {
427417
throw new MarkLogicIOException(e);
428418
}
429419
}
430-
private TransformerFactory makeTransformer() {
431-
TransformerFactory factory = TransformerFactory.newInstance();
432-
// default to best practices for conservative security including recommendations per
433-
// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md
434-
try {
435-
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
436-
} catch (TransformerConfigurationException e) {}
437-
try {
438-
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
439-
} catch (IllegalArgumentException e) {}
440-
try {
441-
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
442-
} catch (IllegalArgumentException e) {}
443-
return factory;
420+
private TransformerFactory makeTransformerFactory() {
421+
return XmlFactories.makeNewTransformerFactory();
444422
}
445423

446424
/**

marklogic-client-api/src/main/java/com/marklogic/client/io/SourceHandle.java

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,17 @@
33
*/
44
package com.marklogic.client.io;
55

6-
import java.io.ByteArrayInputStream;
7-
import java.io.ByteArrayOutputStream;
8-
import java.io.Closeable;
9-
import java.io.IOException;
10-
import java.io.InputStream;
11-
import java.io.InputStreamReader;
12-
import java.io.OutputStream;
13-
import java.io.OutputStreamWriter;
14-
import java.io.UnsupportedEncodingException;
15-
import java.nio.charset.StandardCharsets;
16-
17-
import javax.xml.XMLConstants;
18-
import javax.xml.transform.*;
19-
import javax.xml.transform.stream.StreamResult;
20-
import javax.xml.transform.stream.StreamSource;
21-
6+
import com.marklogic.client.MarkLogicIOException;
7+
import com.marklogic.client.impl.XmlFactories;
228
import com.marklogic.client.io.marker.*;
239
import org.slf4j.Logger;
2410
import org.slf4j.LoggerFactory;
2511

26-
import com.marklogic.client.MarkLogicIOException;
12+
import javax.xml.transform.*;
13+
import javax.xml.transform.stream.StreamResult;
14+
import javax.xml.transform.stream.StreamSource;
15+
import java.io.*;
16+
import java.nio.charset.StandardCharsets;
2717

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

183173
transformer.transform(content, result);
@@ -186,20 +176,8 @@ public void transform(Result result) {
186176
throw new MarkLogicIOException(e);
187177
}
188178
}
189-
private TransformerFactory makeTransformer() {
190-
TransformerFactory factory = TransformerFactory.newInstance();
191-
// default to best practices for conservative security including recommendations per
192-
// https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.md
193-
try {
194-
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
195-
} catch (TransformerConfigurationException e) {}
196-
try {
197-
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
198-
} catch (IllegalArgumentException e) {}
199-
try {
200-
factory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
201-
} catch (IllegalArgumentException e) {}
202-
return factory;
179+
private TransformerFactory makeTransformerFactory() {
180+
return XmlFactories.makeNewTransformerFactory();
203181
}
204182

205183
/**
@@ -260,7 +238,7 @@ public byte[] contentToBytes(Source content) {
260238
if (content == null) return null;
261239
try {
262240
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
263-
makeTransformer().newTransformer().transform(content,
241+
makeTransformerFactory().newTransformer().transform(content,
264242
new StreamResult(new OutputStreamWriter(buffer, StandardCharsets.UTF_8)));
265243
return buffer.toByteArray();
266244
} catch (TransformerException e) {

marklogic-client-api/src/test/java/com/marklogic/client/test/HandleAsTest.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.marklogic.client.document.BinaryDocumentManager;
99
import com.marklogic.client.document.TextDocumentManager;
1010
import com.marklogic.client.document.XMLDocumentManager;
11+
import com.marklogic.client.impl.XmlFactories;
1112
import com.marklogic.client.io.BaseHandle;
1213
import com.marklogic.client.io.Format;
1314
import com.marklogic.client.io.JAXBHandle;
@@ -18,6 +19,8 @@
1819
import com.marklogic.client.query.MatchDocumentSummary;
1920
import com.marklogic.client.query.QueryDefinition;
2021
import com.marklogic.client.query.QueryManager;
22+
import jakarta.xml.bind.JAXBException;
23+
import jakarta.xml.bind.annotation.XmlRootElement;
2124
import org.junit.jupiter.api.AfterAll;
2225
import org.junit.jupiter.api.BeforeAll;
2326
import org.junit.jupiter.api.Test;
@@ -27,16 +30,17 @@
2730
import org.xml.sax.InputSource;
2831
import org.xml.sax.SAXException;
2932

30-
import jakarta.xml.bind.JAXBException;
31-
import jakarta.xml.bind.annotation.XmlRootElement;
3233
import javax.xml.parsers.DocumentBuilder;
3334
import javax.xml.parsers.DocumentBuilderFactory;
3435
import javax.xml.parsers.ParserConfigurationException;
3536
import javax.xml.stream.XMLEventReader;
3637
import javax.xml.stream.XMLInputFactory;
3738
import javax.xml.stream.XMLStreamException;
3839
import javax.xml.stream.XMLStreamReader;
39-
import javax.xml.transform.*;
40+
import javax.xml.transform.Source;
41+
import javax.xml.transform.Transformer;
42+
import javax.xml.transform.TransformerException;
43+
import javax.xml.transform.TransformerFactoryConfigurationError;
4044
import javax.xml.transform.dom.DOMResult;
4145
import javax.xml.transform.dom.DOMSource;
4246
import java.io.*;
@@ -144,7 +148,7 @@ public void testBuiltinReadWrite()
144148
xmlMgr.delete(xmlDocId);
145149
assertEquals(beforeText, afterText);
146150

147-
Transformer transformer = TransformerFactory.newInstance().newTransformer();
151+
Transformer transformer = XmlFactories.makeNewTransformerFactory().newTransformer();
148152

149153
xmlMgr.writeAs(xmlDocId, new DOMSource(beforeDocument));
150154
DOMResult afterResult = new DOMResult();

0 commit comments

Comments
 (0)