diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java index 068ad6a101..c886582979 100644 --- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/IntegrationXmlNamespaceHandler.java @@ -28,6 +28,7 @@ public class IntegrationXmlNamespaceHandler extends NamespaceHandlerSupport { public void init() { registerBeanDefinitionParser("marshalling-transformer", new XmlMarshallingTransformerParser()); registerBeanDefinitionParser("unmarshalling-transformer", new XmlUnmarshallingTransformerParser()); + registerBeanDefinitionParser("xslt-transformer", new XsltPayloadTransformerParser()); } } diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XsltPayloadTransformerParser.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XsltPayloadTransformerParser.java new file mode 100644 index 0000000000..684e6b9871 --- /dev/null +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/XsltPayloadTransformerParser.java @@ -0,0 +1,79 @@ +/* + * 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.config; + +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.xml.transformer.XsltPayloadTransformer; +import org.springframework.util.Assert; +import org.springframework.util.StringUtils; +import org.w3c.dom.Element; + +/** + * + * @author Jonas Partner + * + */ +public class XsltPayloadTransformerParser extends AbstractSingleBeanDefinitionParser { + + @Override + protected boolean shouldGenerateId() { + return false; + } + + @Override + protected boolean shouldGenerateIdAsFallback() { + return true; + } + + @Override + protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { + String xslResource = element.getAttribute("xsl-resource"); + String xslTemplates = element.getAttribute("xsl-templates"); + + boolean bothHaveText = StringUtils.hasText(xslResource) && StringUtils.hasText(xslTemplates); + boolean oneHasText = StringUtils.hasText(xslResource) || StringUtils.hasText(xslTemplates); + + Assert.state(!bothHaveText && oneHasText, + "Exaclty one of xsl-resource or xsl-templates should be specified"); + + builder.getBeanDefinition().setBeanClass(XsltPayloadTransformer.class); + + + if(StringUtils.hasText(xslResource)){ + builder.getBeanDefinition().getConstructorArgumentValues() + .addGenericArgumentValue(new ValueHolder(xslResource)); + } else if (StringUtils.hasText(xslTemplates)){ + builder.getBeanDefinition().getConstructorArgumentValues() + .addGenericArgumentValue(new RuntimeBeanReference(xslTemplates)); + } + + String sourceFactory = element.getAttribute("source-factory"); + if(StringUtils.hasText(sourceFactory)){ + builder.getBeanDefinition().getPropertyValues().addPropertyValue("sourceFactory", new RuntimeBeanReference(sourceFactory)); + } + + String resultFactory = element.getAttribute("result-factory"); + if(StringUtils.hasText(resultFactory)){ + builder.getBeanDefinition().getPropertyValues().addPropertyValue("resultFactory", new RuntimeBeanReference(resultFactory)); + } + } + +} diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd index 35e2d215d6..41079bcf8b 100644 --- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/config/spring-integration-xml-1.0.xsd @@ -52,5 +52,21 @@ + + + + + + Defines a XML unmarshalling transformer. + + + + + + + + + + \ No newline at end of file diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XmlPayloadMarshallingTransformer.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XmlPayloadMarshallingTransformer.java index b114781bec..b4835d1ec5 100644 --- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XmlPayloadMarshallingTransformer.java +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XmlPayloadMarshallingTransformer.java @@ -64,7 +64,7 @@ public class XmlPayloadMarshallingTransformer implements MessageTransformer { transformedPayload = result; } catch (IOException e) { - throw new MessageHandlingException(message, "failed to marshal payload", e); + throw new MessageHandlingException(message, "failed to marshall payload", e); } if (transformedPayload == null) { diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java index 8ccbd75216..cc374b1f9b 100644 --- a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java @@ -16,6 +16,7 @@ package org.springframework.integration.xml.transformer; +import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.TransformerException; @@ -26,8 +27,10 @@ import org.springframework.core.io.Resource; import org.springframework.integration.message.Message; import org.springframework.integration.message.MessagingException; import org.springframework.integration.transformer.MessageTransformer; -import org.springframework.xml.transform.StringResult; -import org.springframework.xml.transform.StringSource; +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.w3c.dom.Document; /** @@ -40,6 +43,10 @@ public class XsltPayloadTransformer implements MessageTransformer { private final Templates templates; + private SourceFactory sourceFactory = new DomSourceFactory(); + + private ResultFactory resultFactory = new DomResultFactory(); + public XsltPayloadTransformer(Templates templates) { this.templates = templates; } @@ -52,12 +59,11 @@ public class XsltPayloadTransformer implements MessageTransformer { public void transform(Message message) { try { if (Source.class.isAssignableFrom(message.getPayload().getClass())) { - this.transformSource(message); + transformSource(message, (Source) message.getPayload()); } else { - throw new MessagingException(message, - "Unsupported payload type for transformation expected javax.xml.transform.Source but got : " - + message.getPayload().getClass().getName()); + Source source = sourceFactory.getSourceForMessage(message); + transformSource(message, source); } } catch (TransformerException e) { @@ -66,10 +72,18 @@ public class XsltPayloadTransformer implements MessageTransformer { } @SuppressWarnings("unchecked") - protected void transformSource(Message message) throws TransformerException { - StringResult result = new StringResult(); - this.templates.newTransformer().transform((Source) message.getPayload(), result); - message.setPayload(new StringSource(result.toString())); + protected void transformSource(Message message, Source source) throws TransformerException { + Result result = resultFactory.getNewResult(message); + this.templates.newTransformer().transform(source, result); + message.setPayload(result); + } + + public void setSourceFactory(SourceFactory sourceFactory) { + this.sourceFactory = sourceFactory; + } + + public void setResultFactory(ResultFactory resultFactory) { + this.resultFactory = resultFactory; } } diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/TestTemplatesFactory.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/TestTemplatesFactory.java new file mode 100644 index 0000000000..f44077b758 --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/TestTemplatesFactory.java @@ -0,0 +1,48 @@ +/* + * 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.config; + +import javax.xml.transform.Templates; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamSource; + +import org.springframework.beans.factory.FactoryBean; +import org.springframework.core.io.ClassPathResource; + +/** + * + * @author Jonas Partner + * + */ +public class TestTemplatesFactory implements FactoryBean { + + public Object getObject() throws Exception { + org.springframework.core.io.Resource xslResource = new ClassPathResource("test.xsl", getClass()); + return TransformerFactory.newInstance().newTemplates(new StreamSource(xslResource.getInputStream())); + } + + @SuppressWarnings("unchecked") + public Class getObjectType() { + return Templates.class; + } + + public boolean isSingleton() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests-context.xml b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests-context.xml new file mode 100644 index 0000000000..925c482e44 --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests-context.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests.java new file mode 100644 index 0000000000..5f6f53231e --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/XsltPayloadTransformerParserTests.java @@ -0,0 +1,65 @@ +/* + * 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.config; + +import static org.junit.Assert.*; + +import javax.xml.transform.dom.DOMResult; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.integration.message.GenericMessage; +import org.springframework.integration.transformer.MessageTransformer; +import org.springframework.integration.xml.util.XmlTestUtil; +import org.w3c.dom.Document; + +public class XsltPayloadTransformerParserTests { + + String doc = "test"; + + ApplicationContext applicationContext; + + @Before + public void setUp() { + applicationContext = new ClassPathXmlApplicationContext(getClass().getSimpleName() + "-context.xml", getClass()); + } + + @Test + public void testWithResourceProvided() throws Exception { + MessageTransformer messageTransformer = (MessageTransformer) applicationContext + .getBean("xsltTransfomerWithResource"); + GenericMessage message = new GenericMessage(XmlTestUtil.getDomSourceForString(doc)); + messageTransformer.transform(message); + assertTrue("Payload was not a DOMResult", message.getPayload() instanceof DOMResult); + Document doc = (Document) ((DOMResult) message.getPayload()).getNode(); + assertEquals("Wrong palyoad", "test", doc.getDocumentElement().getTextContent()); + } + + @Test + public void testWithTemplatesProvided() throws Exception { + MessageTransformer messageTransformer = (MessageTransformer) applicationContext + .getBean("xsltTransformerWithTemplates"); + GenericMessage message = new GenericMessage(XmlTestUtil.getDomSourceForString(doc)); + messageTransformer.transform(message); + assertTrue("Payload was not a DOMResult", message.getPayload() instanceof DOMResult); + Document doc = (Document) ((DOMResult) message.getPayload()).getNode(); + assertEquals("Wrong palyoad", "test", doc.getDocumentElement().getTextContent()); + } + +} diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/test.xsl b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/test.xsl new file mode 100644 index 0000000000..e7856db28a --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/config/test.xsl @@ -0,0 +1,7 @@ + + + + test + + \ No newline at end of file diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTest.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTest.java index fd8fe19a3d..f453344f75 100644 --- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTest.java +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTest.java @@ -17,11 +17,7 @@ package org.springframework.integration.xml.transformer; import static org.junit.Assert.assertEquals; -import java.io.StringReader; - -import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; -import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import org.junit.Before; @@ -31,9 +27,9 @@ import org.springframework.core.io.Resource; import org.springframework.integration.message.GenericMessage; import org.springframework.integration.message.MessagingException; import org.springframework.integration.message.StringMessage; +import org.springframework.integration.xml.util.XmlTestUtil; import org.springframework.xml.transform.StringSource; import org.w3c.dom.Document; -import org.xml.sax.InputSource; /** * @@ -44,26 +40,34 @@ public class XsltPayloadTransformerTest { XsltPayloadTransformer transformer; + String doc = "test"; + @Before public void setUp() throws Exception { transformer = new XsltPayloadTransformer(getXslResource()); } - @Test(expected = MessagingException.class) - public void testDocumentAsPayloadShouldBeRejected() throws Exception { - Document input = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse( - new InputSource(new StringReader(getInputString()))); - GenericMessage documentMessage = new GenericMessage(input); + @Test + public void testDocumentAsPayload() throws Exception { + GenericMessage documentMessage = new GenericMessage(XmlTestUtil.getDocumentForString(doc)); transformer.transform(documentMessage); + } @Test public void testSourceAsPayload() throws Exception { - GenericMessage message = new GenericMessage(new StringSource(getInputString())); + GenericMessage message = new GenericMessage(new StringSource(doc)); transformer.transform(message); + DOMResult result = (DOMResult) message.getPayload(); + String rootNodeName = ((Document) result.getNode()).getDocumentElement().getNodeName(); + assertEquals("Wrong name for root element after transform", "bob", rootNodeName); + } - DOMResult result = new DOMResult(); - TransformerFactory.newInstance().newTransformer().transform(message.getPayload(), result); + @Test + public void testStringAsPayload() throws Exception { + GenericMessage message = new GenericMessage(doc); + transformer.transform(message); + DOMResult result = (DOMResult) message.getPayload(); String rootNodeName = ((Document) result.getNode()).getDocumentElement().getNodeName(); assertEquals("Wrong name for root element after transform", "bob", rootNodeName); } @@ -78,10 +82,6 @@ public class XsltPayloadTransformerTest { transformer.transform(new GenericMessage(new Long(12))); } - public String getInputString() { - return "test"; - } - public Resource getXslResource() throws Exception { String xsl = "test"; return new ByteArrayResource(xsl.getBytes("UTF-8"));