Updated logic to make it easier to wrok with XML as Document and String payloads INT-311
This commit is contained in:
@@ -24,25 +24,24 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
|
||||
import org.springframework.integration.message.MessagingException;
|
||||
import org.springframework.xml.transform.StringResult;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import org.springframework.integration.message.MessagingException;
|
||||
import org.springframework.integration.transformer.PayloadTransformer;
|
||||
import org.springframework.xml.transform.StringResult;
|
||||
|
||||
/**
|
||||
* Creates a {@link Document} from a {@link Result} payload.
|
||||
* Creates a {@link Document} from a {@link Result} payload. Supports
|
||||
* {@link DOMResult} and {@link StringResult} implementations.
|
||||
*
|
||||
* @author Jonas Partner
|
||||
*/
|
||||
public class ResultToDocumentTransformer implements PayloadTransformer<Result, Document> {
|
||||
public class ResultToDocumentTransformer implements ResultTransformer {
|
||||
|
||||
// Not guaranteed to be thread safe
|
||||
private final DocumentBuilderFactory documentBuilderFactory;
|
||||
|
||||
|
||||
public ResultToDocumentTransformer(DocumentBuilderFactory documentBuilderFactory) {
|
||||
public ResultToDocumentTransformer(
|
||||
DocumentBuilderFactory documentBuilderFactory) {
|
||||
this.documentBuilderFactory = documentBuilderFactory;
|
||||
}
|
||||
|
||||
@@ -50,19 +49,16 @@ public class ResultToDocumentTransformer implements PayloadTransformer<Result, D
|
||||
this(DocumentBuilderFactory.newInstance());
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Document transform(Result payload) {
|
||||
public Object transformResult(Result res) {
|
||||
Document doc = null;
|
||||
if (DOMResult.class.isAssignableFrom(payload.getClass())) {
|
||||
doc = createDocumentFromDomResult((DOMResult) payload);
|
||||
}
|
||||
else if (StringResult.class.isAssignableFrom(payload.getClass())) {
|
||||
doc = createDocumentFromStringResult((StringResult) payload);
|
||||
}
|
||||
else {
|
||||
throw new MessagingException("Failed to create document from payload type ["
|
||||
+ payload.getClass().getName() + "]");
|
||||
if (DOMResult.class.isAssignableFrom(res.getClass())) {
|
||||
doc = createDocumentFromDomResult((DOMResult) res);
|
||||
} else if (StringResult.class.isAssignableFrom(res.getClass())) {
|
||||
doc = createDocumentFromStringResult((StringResult) res);
|
||||
} else {
|
||||
throw new MessagingException(
|
||||
"Failed to create document from payload type ["
|
||||
+ res.getClass().getName() + "]");
|
||||
}
|
||||
return doc;
|
||||
}
|
||||
@@ -73,19 +69,20 @@ public class ResultToDocumentTransformer implements PayloadTransformer<Result, D
|
||||
|
||||
protected Document createDocumentFromStringResult(StringResult stringResult) {
|
||||
try {
|
||||
return getDocumentBuilder().parse(new InputSource(new StringReader(stringResult.toString())));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessagingException("Failed to create Document from StringResult payload", e);
|
||||
return getDocumentBuilder().parse(
|
||||
new InputSource(new StringReader(stringResult.toString())));
|
||||
} catch (Exception e) {
|
||||
throw new MessagingException(
|
||||
"Failed to create Document from StringResult payload", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized DocumentBuilder getDocumentBuilder() {
|
||||
try {
|
||||
return this.documentBuilderFactory.newDocumentBuilder();
|
||||
}
|
||||
catch (ParserConfigurationException e) {
|
||||
throw new MessagingException("Failed to create a new DocumentBuilder", e);
|
||||
} catch (ParserConfigurationException e) {
|
||||
throw new MessagingException(
|
||||
"Failed to create a new DocumentBuilder", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2002-2007 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.integration.xml.transformer;
|
||||
|
||||
public interface ResultTransformer {
|
||||
|
||||
Object transformResult(javax.xml.transform.Result res);
|
||||
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class XmlPayloadMarshallingTransformer implements PayloadTransformer<Obje
|
||||
|
||||
private final Marshaller marshaller;
|
||||
|
||||
private ResultFactory resultFactory;
|
||||
private ResultFactory resultFactory = new DomResultFactory();
|
||||
|
||||
|
||||
public XmlPayloadMarshallingTransformer(Marshaller marshaller) throws ParserConfigurationException {
|
||||
|
||||
@@ -22,43 +22,69 @@ import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.message.MessagingException;
|
||||
import org.springframework.integration.transformer.PayloadTransformer;
|
||||
import org.springframework.integration.xml.result.DomResultFactory;
|
||||
import org.springframework.integration.xml.result.ResultFactory;
|
||||
import org.springframework.integration.xml.source.DomSourceFactory;
|
||||
import org.springframework.integration.xml.source.SourceFactory;
|
||||
import org.springframework.xml.transform.StringResult;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* Simple XSLT transformer implementation which returns a transformed
|
||||
* {@link Source}, {@link Document}, or {@link String}.
|
||||
* XSLT transformer implementation which returns a transformed {@link Source},
|
||||
* {@link Document}, or {@link String}. If alwaysUseSourceResultFactories is
|
||||
* false (default) the following logic occurs
|
||||
*
|
||||
* {@link String} payload in results in {@link String} payload out
|
||||
*
|
||||
* {@link Document} payload in {@link Document} payload out
|
||||
*
|
||||
* {@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.
|
||||
*
|
||||
* 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
|
||||
* returnign
|
||||
*
|
||||
*
|
||||
* @author Jonas Partner
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class XsltPayloadTransformer implements PayloadTransformer<Object, Result> {
|
||||
public class XsltPayloadTransformer implements
|
||||
PayloadTransformer<Object, Object> {
|
||||
|
||||
private final Templates templates;
|
||||
|
||||
private SourceFactory sourceFactory = new DomSourceFactory();
|
||||
|
||||
private ResultFactory resultFactory;
|
||||
private ResultFactory resultFactory = new DomResultFactory();
|
||||
|
||||
private boolean alwaysUseSourceResultFactories = false;
|
||||
|
||||
public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException {
|
||||
private ResultTransformer resultTransformer;
|
||||
|
||||
public XsltPayloadTransformer(Templates templates)
|
||||
throws ParserConfigurationException {
|
||||
this.templates = templates;
|
||||
resultFactory = new DomResultFactory();
|
||||
}
|
||||
|
||||
public XsltPayloadTransformer(Resource xslResource) throws Exception {
|
||||
this(TransformerFactory.newInstance().newTemplates(new StreamSource(xslResource.getInputStream())));
|
||||
this(TransformerFactory.newInstance().newTemplates(
|
||||
new StreamSource(xslResource.getInputStream())));
|
||||
}
|
||||
|
||||
|
||||
public void setSourceFactory(SourceFactory sourceFactory) {
|
||||
this.sourceFactory = sourceFactory;
|
||||
}
|
||||
@@ -67,18 +93,69 @@ public class XsltPayloadTransformer implements PayloadTransformer<Object, Result
|
||||
this.resultFactory = resultFactory;
|
||||
}
|
||||
|
||||
public Result transform(Object payload) throws TransformerException {
|
||||
if (Source.class.isAssignableFrom(payload.getClass())) {
|
||||
return this.transformSource((Source) payload);
|
||||
}
|
||||
Source source = this.sourceFactory.createSource(payload);
|
||||
return this.transformSource(source);
|
||||
public void setAlwaysUseSourceResultFactories(
|
||||
boolean alwaysUserSourceResultFactories) {
|
||||
this.alwaysUseSourceResultFactories = alwaysUserSourceResultFactories;
|
||||
}
|
||||
|
||||
protected Result transformSource(Source source) throws TransformerException {
|
||||
Result result = resultFactory.createResult(source);
|
||||
public Object transform(Object payload) throws TransformerException {
|
||||
Object transformedPayload;
|
||||
if (alwaysUseSourceResultFactories) {
|
||||
transformedPayload = transformUsingFactories(payload);
|
||||
} else if (payload instanceof String) {
|
||||
transformedPayload = transformString((String) payload);
|
||||
} else if (Document.class.isAssignableFrom(payload.getClass())) {
|
||||
transformedPayload = transformDocument((Document) payload);
|
||||
} else if (Source.class.isAssignableFrom(payload.getClass())) {
|
||||
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 transformSource(Source source, Object payload)
|
||||
throws TransformerException {
|
||||
Result result = resultFactory.createResult(payload);
|
||||
this.templates.newTransformer().transform(source, result);
|
||||
return result;
|
||||
if (resultTransformer != null) {
|
||||
return resultTransformer.transformResult(result);
|
||||
} else {
|
||||
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 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();
|
||||
}
|
||||
|
||||
public void setResultTransformer(ResultTransformer resultTransformer) {
|
||||
this.resultTransformer = resultTransformer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.integration.xml.source;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.custommonkey.xmlunit.XMLAssert.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
||||
@@ -49,7 +49,7 @@ public class ResultToDocumentTransformerTests {
|
||||
@Test
|
||||
public void testWithDomResult() throws Exception {
|
||||
DOMResult result = XmlTestUtil.getDomResultForString(doc);
|
||||
Object transformed = resToDocTransformer.transform(result);
|
||||
Object transformed = resToDocTransformer.transformResult(result);
|
||||
assertTrue("Wrong transformed type expected Document", transformed instanceof Document);
|
||||
Document doc = (Document) transformed;
|
||||
assertEquals("Wrong root element name", "order", doc.getDocumentElement().getNodeName());
|
||||
@@ -58,7 +58,7 @@ public class ResultToDocumentTransformerTests {
|
||||
@Test
|
||||
public void testWithStringResult() throws Exception {
|
||||
StringResult result = XmlTestUtil.getStringResultForString(doc);
|
||||
Object transformed = resToDocTransformer.transform(result);
|
||||
Object transformed = resToDocTransformer.transformResult(result);
|
||||
assertTrue("Wrong transformed type expected Document", transformed instanceof Document);
|
||||
Document doc = (Document) transformed;
|
||||
assertEquals("Wrong root element name", "order", doc.getDocumentElement().getNodeName());
|
||||
@@ -67,7 +67,7 @@ public class ResultToDocumentTransformerTests {
|
||||
@Test(expected = MessagingException.class)
|
||||
public void testWithUnsupportedSaxResult() throws Exception {
|
||||
SAXResult result = new SAXResult();
|
||||
resToDocTransformer.transform(result);
|
||||
resToDocTransformer.transformResult(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,20 +16,22 @@
|
||||
|
||||
package org.springframework.integration.xml.transformer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual;
|
||||
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.integration.message.MessagingException;
|
||||
import org.springframework.integration.xml.util.XmlTestUtil;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
/**
|
||||
* @author Jonas Partner
|
||||
@@ -38,40 +40,72 @@ public class XsltPayloadTransformerTest {
|
||||
|
||||
private XsltPayloadTransformer transformer;
|
||||
|
||||
private String doc = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><order><orderItem>test</orderItem></order>";
|
||||
private String docAsString = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><order><orderItem>test</orderItem></order>";
|
||||
|
||||
private String outputAsString = "<bob>test</bob>";
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
transformer = new XsltPayloadTransformer(getXslResource());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDocumentAsPayload() throws Exception {
|
||||
Object transformed = transformer.transform(XmlTestUtil.getDocumentForString(doc));
|
||||
DOMResult result = (DOMResult) transformed;
|
||||
String rootNodeName = ((Document) result.getNode()).getDocumentElement().getNodeName();
|
||||
assertEquals("Wrong name for root element after transform", "bob", rootNodeName);
|
||||
Object transformed = transformer.transform(XmlTestUtil
|
||||
.getDocumentForString(docAsString));
|
||||
assertTrue("Wrong return type for document payload", Document.class
|
||||
.isAssignableFrom(transformed.getClass()));
|
||||
Document transformedDocument = (Document) transformed;
|
||||
assertXMLEqual(outputAsString, XmlTestUtil
|
||||
.docToString(transformedDocument));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSourceAsPayload() throws Exception {
|
||||
Object transformed = transformer.transform(new StringSource(doc));
|
||||
Object transformed = transformer
|
||||
.transform(new StringSource(docAsString));
|
||||
assertEquals("Wrong return type for source payload", DOMResult.class,
|
||||
transformed.getClass());
|
||||
DOMResult result = (DOMResult) transformed;
|
||||
String rootNodeName = ((Document) result.getNode()).getDocumentElement().getNodeName();
|
||||
assertEquals("Wrong name for root element after transform", "bob", rootNodeName);
|
||||
assertXMLEqual("Document incorrect after transformation", XmlTestUtil
|
||||
.getDocumentForString(outputAsString), (Document) result
|
||||
.getNode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringAsPayload() throws Exception {
|
||||
Object transformed = transformer.transform(doc);
|
||||
DOMResult result = (DOMResult) transformed;
|
||||
String rootNodeName = ((Document) result.getNode()).getDocumentElement().getNodeName();
|
||||
assertEquals("Wrong name for root element after transform", "bob", rootNodeName);
|
||||
Object transformed = transformer.transform(docAsString);
|
||||
assertEquals("Wrong return type for string payload", String.class,
|
||||
transformed.getClass());
|
||||
String transformedString = (String) transformed;
|
||||
assertXMLEqual("String incorrect after transform", outputAsString,
|
||||
transformedString);
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
@Test
|
||||
public void testStringAsPayloadUseFactoriesTrue() throws Exception {
|
||||
transformer.setAlwaysUseSourceResultFactories(true);
|
||||
Object transformed = transformer.transform(docAsString);
|
||||
assertEquals("Wrong return type for useFactories true",
|
||||
DOMResult.class, transformed.getClass());
|
||||
DOMResult result = (DOMResult) transformed;
|
||||
assertXMLEqual("Document incorrect after transformation", XmlTestUtil
|
||||
.getDocumentForString(outputAsString), (Document) result
|
||||
.getNode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSourceWithResultTransformer() throws Exception {
|
||||
Integer returnValue = new Integer(13);
|
||||
transformer
|
||||
.setResultTransformer(new StubResultTransformer(returnValue));
|
||||
Object transformed = transformer
|
||||
.transform(new StringSource(docAsString));
|
||||
assertEquals("Wrong value from result conversion", returnValue,
|
||||
transformed);
|
||||
}
|
||||
|
||||
@Test(expected = TransformerException.class)
|
||||
public void testNonXmlString() throws Exception {
|
||||
transformer.transform("test");
|
||||
}
|
||||
@@ -81,10 +115,23 @@ public class XsltPayloadTransformerTest {
|
||||
transformer.transform(new Long(12));
|
||||
}
|
||||
|
||||
|
||||
private Resource getXslResource() throws Exception {
|
||||
String xsl = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"><xsl:template match=\"order\"><bob>test</bob></xsl:template></xsl:stylesheet>";
|
||||
return new ByteArrayResource(xsl.getBytes("UTF-8"));
|
||||
}
|
||||
|
||||
public static class StubResultTransformer implements ResultTransformer {
|
||||
|
||||
private Object objToReturn;
|
||||
|
||||
public StubResultTransformer(Object objToReturn) {
|
||||
this.objToReturn = objToReturn;
|
||||
}
|
||||
|
||||
public Object transformResult(Result res) {
|
||||
return objToReturn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +60,14 @@ public class XmlTestUtil {
|
||||
return res;
|
||||
}
|
||||
|
||||
public static String docToString(Document doc) throws Exception{
|
||||
DOMSource source = new DOMSource(doc);
|
||||
StringResult stringResult = new StringResult();
|
||||
transform(source, stringResult);
|
||||
return stringResult.toString();
|
||||
}
|
||||
|
||||
|
||||
public static void transform(Source source, Result res) throws Exception {
|
||||
TransformerFactory.newInstance().newTransformer().transform(source, res);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user