diff --git a/src/main/java/com/jcabi/xml/XSLDocument.java b/src/main/java/com/jcabi/xml/XSLDocument.java
index d7855be..14eec80 100644
--- a/src/main/java/com/jcabi/xml/XSLDocument.java
+++ b/src/main/java/com/jcabi/xml/XSLDocument.java
@@ -357,7 +357,9 @@ public String toString() {
public XML transform(final XML xml) {
final DocumentBuilder builder;
try {
- builder = XSLDocument.DFACTORY.newDocumentBuilder();
+ synchronized (XSLDocument.DFACTORY) {
+ builder = XSLDocument.DFACTORY.newDocumentBuilder();
+ }
} catch (final ParserConfigurationException ex) {
throw new IllegalArgumentException(
String.format(
@@ -397,7 +399,7 @@ public String applyTo(final XML xml) {
* @param xml XML
* @param result Result
* @since 0.11
- * @link https://stackoverflow.com/questions/4695489/capture-xslmessage-output-in-java
+ * @link Relevant SO question
*/
private void transformInto(final XML xml, final Result result) {
final Transformer trans = this.transformer();
@@ -405,7 +407,9 @@ private void transformInto(final XML xml, final Result result) {
trans.setErrorListener(errors);
final long start = System.nanoTime();
try {
- trans.transform(new DOMSource(xml.node()), result);
+ synchronized (XSLDocument.DFACTORY) {
+ trans.transform(new DOMSource(xml.node()), result);
+ }
} catch (final TransformerException ex) {
throw new IllegalArgumentException(
String.format(
@@ -431,10 +435,10 @@ private void transformInto(final XML xml, final Result result) {
* @return The transformer
*/
private Transformer transformer() {
- if (this.cached.get() == null) {
- final Transformer trans;
- synchronized (XSLDocument.TFACTORY) {
+ synchronized (XSLDocument.TFACTORY) {
+ if (this.cached.get() == null) {
XSLDocument.TFACTORY.setURIResolver(this.sources);
+ final Transformer trans;
try {
trans = XSLDocument.TFACTORY.newTransformer(
new StreamSource(new StringReader(this.xsl), this.sid)
@@ -448,11 +452,11 @@ private Transformer transformer() {
ex
);
}
+ for (final Map.Entry ent : this.params.entrySet()) {
+ trans.setParameter(ent.getKey(), ent.getValue());
+ }
+ this.cached.set(XSLDocument.forSaxon(trans));
}
- for (final Map.Entry ent : this.params.entrySet()) {
- trans.setParameter(ent.getKey(), ent.getValue());
- }
- this.cached.set(XSLDocument.forSaxon(trans));
}
return this.cached.get();
}
diff --git a/src/test/java/com/jcabi/xml/XSLDocumentTest.java b/src/test/java/com/jcabi/xml/XSLDocumentTest.java
index 1154ab0..b406a13 100644
--- a/src/test/java/com/jcabi/xml/XSLDocumentTest.java
+++ b/src/test/java/com/jcabi/xml/XSLDocumentTest.java
@@ -230,13 +230,14 @@ void transformsInManyThreads() throws Exception {
);
final AtomicInteger done = new AtomicInteger(0);
final CountDownLatch latch = new CountDownLatch(1);
- final int total = 10;
+ final int total = 50;
final ExecutorService exec = Executors.newFixedThreadPool(total);
for (int task = 0; task < total; ++task) {
exec.submit(
() -> {
latch.await();
xsl.transform(xml);
+ xsl.transform(xml);
done.incrementAndGet();
return 0;
}