SWS-643 - Create TransformerHelper class

This commit is contained in:
Arjen Poutsma
2010-09-21 13:49:32 +00:00
parent 920309cfc5
commit efb3f194cb
3 changed files with 218 additions and 33 deletions

View File

@@ -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.
* <p/>
* 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.
* <p/>
* 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);
}
}

View File

@@ -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.
* <p>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.
* <p>Can be overridden in subclasses.
* Instantiate a new TransformerFactory. <p>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. <p>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 <code>TransformerFactory</code>. */
/**
* Returns the <code>TransformerFactory</code>.
*/
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);
}
}

View File

@@ -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 = "<root xmlns='http://springframework.org/spring-ws'><child>text</child></root>";
Source source = new StringSource(xml);
Result result = new StringResult();
helper.transform(source, result);
assertXMLEqual(xml, result.toString());
}
}