Updated logic to make it easier to wrok with XML as Document and String payloads INT-311

This commit is contained in:
Jonas Partner
2008-08-19 08:42:55 +00:00
parent d55c89e170
commit 94746fb6a4
8 changed files with 219 additions and 69 deletions

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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 {

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}