diff --git a/xml/src/main/java/org/springframework/xml/transform/TransformerHelper.java b/xml/src/main/java/org/springframework/xml/transform/TransformerHelper.java new file mode 100644 index 00000000..7fe8bf1c --- /dev/null +++ b/xml/src/main/java/org/springframework/xml/transform/TransformerHelper.java @@ -0,0 +1,141 @@ +/* + * Copyright 2005-2010 the original author or authors. + * + * Licensed 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.springframework.xml.transform; + +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 javax.xml.transform.TransformerFactoryConfigurationError; + +import org.springframework.util.Assert; + +/** + * Helper class for {@link Transformer} usage. Provides {@link #createTransformer()} and {@link #transform(Source, + * Result)}. + * + * @author Arjen Poutsma + * @since 3.0 + */ +public class TransformerHelper { + + private volatile TransformerFactory transformerFactory; + + private Class extends TransformerFactory> transformerFactoryClass; + + /** + * Initializes a new instance of the {@code TransformerHelper}. + */ + public TransformerHelper() { + } + + /** + * Initializes a new instance of the {@code TransformerHelper} with the specified {@link TransformerFactory}. + */ + public TransformerHelper(TransformerFactory transformerFactory) { + this.transformerFactory = transformerFactory; + } + + /** + * Initializes a new instance of the {@code TransformerHelper} with the specified {@link TransformerFactory} class. + */ + public TransformerHelper(Class extends TransformerFactory> transformerFactoryClass) { + setTransformerFactoryClass(transformerFactoryClass); + } + + /** + * Specify the {@code TransformerFactory} class to use. + */ + public void setTransformerFactoryClass(Class extends TransformerFactory> transformerFactoryClass) { + Assert.isAssignable(TransformerFactory.class, transformerFactoryClass); + this.transformerFactoryClass = transformerFactoryClass; + } + + /** + * Instantiate a new TransformerFactory. + *
+ * The default implementation simply calls {@link TransformerFactory#newInstance()}. If a {@link + * #setTransformerFactoryClass transformerFactoryClass} has been specified explicitly, the default constructor of + * the specified class will be called instead. + * + * Can be overridden in subclasses. + * + * @param transformerFactoryClass the specified factory class (if any) + * @return the new TransactionFactory instance + * @see #setTransformerFactoryClass + * @see #getTransformerFactory() + */ + protected TransformerFactory newTransformerFactory(Class extends TransformerFactory> transformerFactoryClass) { + if (transformerFactoryClass != null) { + try { + return transformerFactoryClass.newInstance(); + } + catch (Exception ex) { + throw new TransformerFactoryConfigurationError(ex, + "Could not instantiate TransformerFactory [" + transformerFactoryClass + "]"); + } + } + else { + return TransformerFactory.newInstance(); + } + } + + /** + * Returns the {@code TransformerFactory}. + * + * @return the transformer factory + */ + public TransformerFactory getTransformerFactory() { + TransformerFactory result = transformerFactory; + if (result == null) { + synchronized (this) { + result = transformerFactory; + if (result == null) { + transformerFactory = result = newTransformerFactory(transformerFactoryClass); + } + } + } + return result; + } + + /** + * Creates a new {@code Transformer}. Must be called per thread, as transformers are not thread-safe. + * + * @return the created transformer + * @throws TransformerConfigurationException + * if thrown by JAXP methods + */ + public Transformer createTransformer() throws TransformerConfigurationException { + return getTransformerFactory().newTransformer(); + } + + /** + * Transforms the given {@link Source} to the given {@link Result}. Creates a new {@link Transformer} for every + * call, as transformers are not thread-safe. + * + * @param source the source to transform from + * @param result the result to transform to + * @throws TransformerException if thrown by JAXP methods + */ + public void transform(Source source, Result result) throws TransformerException { + Transformer transformer = createTransformer(); + transformer.transform(source, result); + } + +} diff --git a/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java b/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java index e2b2e9db..3f827430 100644 --- a/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java +++ b/xml/src/main/java/org/springframework/xml/transform/TransformerObjectSupport.java @@ -22,9 +22,6 @@ import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; -import javax.xml.transform.TransformerFactoryConfigurationError; - -import org.springframework.util.Assert; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -40,52 +37,40 @@ import org.apache.commons.logging.LogFactory; */ public abstract class TransformerObjectSupport { - /** Logger available to subclasses. */ + /** + * Logger available to subclasses. + */ protected final Log logger = LogFactory.getLog(getClass()); - private TransformerFactory transformerFactory; - - private Class extends TransformerFactory> transformerFactoryClass; + private TransformerHelper transformerHelper = new TransformerHelper(); /** * Specify the {@code TransformerFactory} class to use. */ public void setTransformerFactoryClass(Class extends TransformerFactory> transformerFactoryClass) { - Assert.isAssignable(TransformerFactory.class, transformerFactoryClass); - this.transformerFactoryClass = transformerFactoryClass; + transformerHelper.setTransformerFactoryClass(transformerFactoryClass); } /** - * Instantiate a new TransformerFactory. - *The default implementation simply calls {@link TransformerFactory#newInstance()}. - * If a {@link #setTransformerFactoryClass "transformerFactoryClass"} has been specified explicitly, - * the default constructor of the specified class will be called instead. - *
Can be overridden in subclasses. + * Instantiate a new TransformerFactory.
The default implementation simply calls {@link + * TransformerFactory#newInstance()}. If a {@link #setTransformerFactoryClass "transformerFactoryClass"} has been + * specified explicitly, the default constructor of the specified class will be called instead.
Can be overridden
+ * in subclasses.
+ *
* @param transformerFactoryClass the specified factory class (if any)
* @return the new TransactionFactory instance
* @see #setTransformerFactoryClass
* @see #getTransformerFactory()
*/
protected TransformerFactory newTransformerFactory(Class extends TransformerFactory> transformerFactoryClass) {
- if (transformerFactoryClass != null) {
- try {
- return transformerFactoryClass.newInstance();
- }
- catch (Exception ex) {
- throw new TransformerFactoryConfigurationError(ex, "Could not instantiate TransformerFactory");
- }
- }
- else {
- return TransformerFactory.newInstance();
- }
+ return transformerHelper.newTransformerFactory(transformerFactoryClass);
}
- /** Returns the TransformerFactory. */
+ /**
+ * Returns the TransformerFactory.
+ */
protected TransformerFactory getTransformerFactory() {
- if (transformerFactory == null) {
- transformerFactory = newTransformerFactory(transformerFactoryClass);
- }
- return transformerFactory;
+ return transformerHelper.getTransformerFactory();
}
/**
@@ -96,7 +81,7 @@ public abstract class TransformerObjectSupport {
* if thrown by JAXP methods
*/
protected final Transformer createTransformer() throws TransformerConfigurationException {
- return getTransformerFactory().newTransformer();
+ return transformerHelper.createTransformer();
}
/**
@@ -108,8 +93,7 @@ public abstract class TransformerObjectSupport {
* @throws TransformerException if thrown by JAXP methods
*/
protected final void transform(Source source, Result result) throws TransformerException {
- Transformer transformer = createTransformer();
- transformer.transform(source, result);
+ transformerHelper.transform(source, result);
}
}
diff --git a/xml/src/test/java/org/springframework/xml/transform/TransformerHelperTest.java b/xml/src/test/java/org/springframework/xml/transform/TransformerHelperTest.java
new file mode 100644
index 00000000..273622cf
--- /dev/null
+++ b/xml/src/test/java/org/springframework/xml/transform/TransformerHelperTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2005-2010 the original author or authors.
+ *
+ * Licensed 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.springframework.xml.transform;
+
+import java.io.IOException;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.TransformerException;
+
+import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
+
+public class TransformerHelperTest {
+
+ private TransformerHelper helper;
+
+ @Before
+ public void setUp() throws Exception {
+ helper = new TransformerHelper();
+ }
+
+ @Test
+ public void defaultTransformerFactory() throws TransformerException, IOException, SAXException {
+ doTest();
+ }
+
+ @Test
+ public void customTransformerFactory() throws TransformerException, IOException, SAXException {
+ helper.setTransformerFactoryClass(TransformerFactoryImpl.class);
+ doTest();
+ }
+
+ private void doTest() throws TransformerException, SAXException, IOException {
+ String xml = "