|
|
|
|
@@ -39,146 +39,158 @@ import org.springframework.util.Assert;
|
|
|
|
|
import org.springframework.xml.transform.StringResult;
|
|
|
|
|
import org.springframework.xml.transform.StringSource;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Thread safe XSLT transformer implementation which returns a transformed {@link Source},
|
|
|
|
|
* {@link Document}, or {@link String}. If alwaysUseSourceResultFactories is
|
|
|
|
|
* false (default) the following logic occurs
|
|
|
|
|
*
|
|
|
|
|
* <p/>
|
|
|
|
|
* {@link String} payload in results in {@link String} payload out
|
|
|
|
|
*
|
|
|
|
|
* <p/>
|
|
|
|
|
* {@link Document} payload in {@link Document} payload out
|
|
|
|
|
*
|
|
|
|
|
* <p/>
|
|
|
|
|
* {@link Source} payload in {@link Result} payload out, type will be determined
|
|
|
|
|
* by the {@link ResultFactory}, {@link DomResultFactory} by default. If an
|
|
|
|
|
* instance of {@link ResultTransformer} is registered this will be used to
|
|
|
|
|
* convert the result.
|
|
|
|
|
*
|
|
|
|
|
* <p/>
|
|
|
|
|
* If alwaysUseSourceResultFactories is true then the ResultFactory and
|
|
|
|
|
* {@link SourceFactory} will be used to create the {@link Source} from the
|
|
|
|
|
* payload and the {@link Result} to pass into the transformer. An instance of
|
|
|
|
|
* {@link ResultTransformer} can also be provided to convert the Result prior to
|
|
|
|
|
* returning
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
*
|
|
|
|
|
* @author Jonas Partner
|
|
|
|
|
* @author Mark Fisher
|
|
|
|
|
*/
|
|
|
|
|
public class XsltPayloadTransformer extends AbstractPayloadTransformer<Object, Object> {
|
|
|
|
|
|
|
|
|
|
private final Templates templates;
|
|
|
|
|
private final Templates templates;
|
|
|
|
|
|
|
|
|
|
private final ResultTransformer resultTransformer;
|
|
|
|
|
private final ResultTransformer resultTransformer;
|
|
|
|
|
|
|
|
|
|
private volatile SourceFactory sourceFactory = new DomSourceFactory();
|
|
|
|
|
private volatile SourceFactory sourceFactory = new DomSourceFactory();
|
|
|
|
|
|
|
|
|
|
private volatile ResultFactory resultFactory = new DomResultFactory();
|
|
|
|
|
private volatile ResultFactory resultFactory = new DomResultFactory();
|
|
|
|
|
|
|
|
|
|
private volatile boolean alwaysUseSourceResultFactories = false;
|
|
|
|
|
private volatile boolean alwaysUseSourceResultFactories = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException {
|
|
|
|
|
this(templates, null);
|
|
|
|
|
}
|
|
|
|
|
public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException {
|
|
|
|
|
this(templates, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public XsltPayloadTransformer(Templates templates,
|
|
|
|
|
ResultTransformer resultTransformer)
|
|
|
|
|
throws ParserConfigurationException {
|
|
|
|
|
this.templates = templates;
|
|
|
|
|
this.resultTransformer = resultTransformer;
|
|
|
|
|
}
|
|
|
|
|
public XsltPayloadTransformer(Templates templates,
|
|
|
|
|
ResultTransformer resultTransformer)
|
|
|
|
|
throws ParserConfigurationException {
|
|
|
|
|
this.templates = templates;
|
|
|
|
|
this.resultTransformer = resultTransformer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public XsltPayloadTransformer(Resource xslResource) throws Exception {
|
|
|
|
|
this(TransformerFactory.newInstance().newTemplates(
|
|
|
|
|
new StreamSource(xslResource.getInputStream())),null);
|
|
|
|
|
}
|
|
|
|
|
public XsltPayloadTransformer(Resource xslResource) throws Exception {
|
|
|
|
|
this(TransformerFactory.newInstance().newTemplates(
|
|
|
|
|
createStreamSourceOnResource(xslResource)), null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public XsltPayloadTransformer(Resource xslResource, ResultTransformer resultTransformer) throws Exception {
|
|
|
|
|
this(TransformerFactory.newInstance().newTemplates(
|
|
|
|
|
new StreamSource(xslResource.getInputStream())),resultTransformer);
|
|
|
|
|
}
|
|
|
|
|
public XsltPayloadTransformer(Resource xslResource, ResultTransformer resultTransformer) throws Exception {
|
|
|
|
|
this(TransformerFactory.newInstance().newTemplates(
|
|
|
|
|
createStreamSourceOnResource(xslResource)), resultTransformer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Compensate for the fact that a Resource <i>may</i> not be a File or even addressable through a URI.
|
|
|
|
|
* If it is, we want the created StreamSource to read other resources relative to the provided one, if it
|
|
|
|
|
* isn't, it loads from the default path.
|
|
|
|
|
*/
|
|
|
|
|
private static StreamSource createStreamSourceOnResource(Resource xslResource) throws IOException {
|
|
|
|
|
try {
|
|
|
|
|
String systemId = xslResource.getURI().toString();
|
|
|
|
|
return new StreamSource(xslResource.getInputStream(), systemId);
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
return new StreamSource(xslResource.getInputStream());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param sourceFactory
|
|
|
|
|
*/
|
|
|
|
|
public void setSourceFactory(SourceFactory sourceFactory) {
|
|
|
|
|
Assert.notNull(sourceFactory, "SourceFactory can not be null");
|
|
|
|
|
this.sourceFactory = sourceFactory;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* @param sourceFactory
|
|
|
|
|
*/
|
|
|
|
|
public void setSourceFactory(SourceFactory sourceFactory) {
|
|
|
|
|
Assert.notNull(sourceFactory, "SourceFactory can not be null");
|
|
|
|
|
this.sourceFactory = sourceFactory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param resultFactory
|
|
|
|
|
*/
|
|
|
|
|
public void setResultFactory(ResultFactory resultFactory) {
|
|
|
|
|
Assert.notNull(sourceFactory, "ResultFactory can not be null");
|
|
|
|
|
this.resultFactory = resultFactory;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* @param resultFactory
|
|
|
|
|
*/
|
|
|
|
|
public void setResultFactory(ResultFactory resultFactory) {
|
|
|
|
|
Assert.notNull(sourceFactory, "ResultFactory can not be null");
|
|
|
|
|
this.resultFactory = resultFactory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Forces use of {@link ResultFactory} and {@link SourceFactory} even for
|
|
|
|
|
* directly supported payloads such as {@link String} and {@link Document}
|
|
|
|
|
*
|
|
|
|
|
* @param alwaysUserSourceResultFactories
|
|
|
|
|
*/
|
|
|
|
|
public void setAlwaysUseSourceResultFactories(
|
|
|
|
|
boolean alwaysUserSourceResultFactories) {
|
|
|
|
|
this.alwaysUseSourceResultFactories = alwaysUserSourceResultFactories;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* Forces use of {@link ResultFactory} and {@link SourceFactory} even for
|
|
|
|
|
* directly supported payloads such as {@link String} and {@link Document}
|
|
|
|
|
*
|
|
|
|
|
* @param alwaysUserSourceResultFactories
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
public void setAlwaysUseSourceResultFactories(
|
|
|
|
|
boolean alwaysUserSourceResultFactories) {
|
|
|
|
|
this.alwaysUseSourceResultFactories = alwaysUserSourceResultFactories;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Object transformPayload(Object payload) throws TransformerException {
|
|
|
|
|
Object transformedPayload = null;
|
|
|
|
|
if (this.alwaysUseSourceResultFactories) {
|
|
|
|
|
transformedPayload = transformUsingFactories(payload);
|
|
|
|
|
}
|
|
|
|
|
else if (payload instanceof String) {
|
|
|
|
|
transformedPayload = transformString((String) payload);
|
|
|
|
|
}
|
|
|
|
|
else if (payload instanceof Document) {
|
|
|
|
|
transformedPayload = transformDocument((Document) payload);
|
|
|
|
|
}
|
|
|
|
|
else if (payload instanceof Source) {
|
|
|
|
|
transformedPayload = transformSource((Source) payload, payload);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
// fall back to trying factories
|
|
|
|
|
transformedPayload = transformUsingFactories(payload);
|
|
|
|
|
}
|
|
|
|
|
return transformedPayload;
|
|
|
|
|
}
|
|
|
|
|
@Override
|
|
|
|
|
public Object transformPayload(Object payload) throws TransformerException {
|
|
|
|
|
Object transformedPayload = null;
|
|
|
|
|
if (this.alwaysUseSourceResultFactories) {
|
|
|
|
|
transformedPayload = transformUsingFactories(payload);
|
|
|
|
|
} else if (payload instanceof String) {
|
|
|
|
|
transformedPayload = transformString((String) payload);
|
|
|
|
|
} else if (payload instanceof Document) {
|
|
|
|
|
transformedPayload = transformDocument((Document) payload);
|
|
|
|
|
} else if (payload instanceof Source) {
|
|
|
|
|
transformedPayload = transformSource((Source) payload, payload);
|
|
|
|
|
} else {
|
|
|
|
|
// fall back to trying factories
|
|
|
|
|
transformedPayload = transformUsingFactories(payload);
|
|
|
|
|
}
|
|
|
|
|
return transformedPayload;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Object transformUsingFactories(Object payload) throws TransformerException {
|
|
|
|
|
Source source = sourceFactory.createSource(payload);
|
|
|
|
|
return transformSource(source, payload);
|
|
|
|
|
}
|
|
|
|
|
protected Object transformUsingFactories(Object payload) throws TransformerException {
|
|
|
|
|
Source source = sourceFactory.createSource(payload);
|
|
|
|
|
return transformSource(source, payload);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Object transformSource(Source source, Object payload) throws TransformerException {
|
|
|
|
|
Result result = resultFactory.createResult(payload);
|
|
|
|
|
this.templates.newTransformer().transform(source, result);
|
|
|
|
|
protected Object transformSource(Source source, Object payload) throws TransformerException {
|
|
|
|
|
Result result = resultFactory.createResult(payload);
|
|
|
|
|
this.templates.newTransformer().transform(source, result);
|
|
|
|
|
|
|
|
|
|
if (resultTransformer != null) {
|
|
|
|
|
return resultTransformer.transformResult(result);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
if (resultTransformer != null) {
|
|
|
|
|
return resultTransformer.transformResult(result);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected String transformString(String stringPayload) throws TransformerException {
|
|
|
|
|
StringResult result = new StringResult();
|
|
|
|
|
this.templates.newTransformer().transform(
|
|
|
|
|
new StringSource(stringPayload), result);
|
|
|
|
|
return result.toString();
|
|
|
|
|
}
|
|
|
|
|
protected String transformString(String stringPayload) throws TransformerException {
|
|
|
|
|
StringResult result = new StringResult();
|
|
|
|
|
this.templates.newTransformer().transform(
|
|
|
|
|
new StringSource(stringPayload), result);
|
|
|
|
|
return result.toString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected Document transformDocument(Document documentPayload) throws TransformerException {
|
|
|
|
|
DOMSource source = new DOMSource(documentPayload);
|
|
|
|
|
Result result = resultFactory.createResult(documentPayload);
|
|
|
|
|
if (!DOMResult.class.isAssignableFrom(result.getClass())) {
|
|
|
|
|
throw new MessagingException(
|
|
|
|
|
"Document to Document conversion requires a DOMResult-producing ResultFactory implementation");
|
|
|
|
|
}
|
|
|
|
|
DOMResult domResult = (DOMResult) result;
|
|
|
|
|
this.templates.newTransformer().transform(source, domResult);
|
|
|
|
|
return (Document) domResult.getNode();
|
|
|
|
|
}
|
|
|
|
|
protected Document transformDocument(Document documentPayload) throws TransformerException {
|
|
|
|
|
DOMSource source = new DOMSource(documentPayload);
|
|
|
|
|
Result result = resultFactory.createResult(documentPayload);
|
|
|
|
|
if (!DOMResult.class.isAssignableFrom(result.getClass())) {
|
|
|
|
|
throw new MessagingException(
|
|
|
|
|
"Document to Document conversion requires a DOMResult-producing ResultFactory implementation");
|
|
|
|
|
}
|
|
|
|
|
DOMResult domResult = (DOMResult) result;
|
|
|
|
|
this.templates.newTransformer().transform(source, domResult);
|
|
|
|
|
return (Document) domResult.getNode();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|