diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/DefaultTransformerConfigurer.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/DefaultTransformerConfigurer.java new file mode 100644 index 0000000000..46064e9da6 --- /dev/null +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/DefaultTransformerConfigurer.java @@ -0,0 +1,85 @@ +/* + * Copyright 2002-2008 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; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.transform.Transformer; + +import org.springframework.integration.core.Message; +import org.springframework.integration.core.MessageHeaders; + +import sun.tools.tree.OrExpression; + +/** + * {@link TransformerConfigurer} instance which looks for headers and uses them + * to configure the provided {@link Transformer} instance. For example a header + * names xslt_paramter_X will cause the transfomer to be configured with a + * property names X with the value of the header. A property named + * xslt_output_property_X will cause an output property on the transformer to be + * set with this headers value. + * + * + * @author Jonas Partner + * + */ +public class DefaultTransformerConfigurer implements TransformerConfigurer { + + public void configureTransfomer(Message message, Transformer transformer) { + Map parameters = extractParameterHeaders(message.getHeaders()); + for(String paramName: parameters.keySet()){ + transformer.setParameter(paramName, parameters.get(paramName)); + } + + Map outputProperties = extractOutputPropertyHeaders(message.getHeaders()); + for(String outputPropertyName : outputProperties.keySet()){ + transformer.setOutputProperty(outputPropertyName, outputProperties.get(outputPropertyName)); + } + + } + + protected Map extractOutputPropertyHeaders( + MessageHeaders headers) { + Map parameters = new HashMap(); + int prefixStringLength = XsltHeaders.OUTPUT_PROPERTY.length(); + for (String key : headers.keySet()) { + if (key.startsWith(XsltHeaders.OUTPUT_PROPERTY)) { + Object headerValue = headers.get(key); + if (!(headerValue instanceof String)) { + throw new IllegalArgumentException( + "Xslt Transfomer only support String output properties received header of type" + + headerValue.getClass().getName() + + " for header named " + key); + } + parameters.put(key.substring(prefixStringLength), (String)headerValue); + } + } + return parameters; + } + + protected Map extractParameterHeaders(MessageHeaders headers) { + Map parameters = new HashMap(); + int prefixStringLength = XsltHeaders.PARAMATER.length(); + for (String key : headers.keySet()) { + if (key.startsWith(XsltHeaders.PARAMATER)) { + parameters.put(key.substring(prefixStringLength), headers.get(key)); + } + } + return parameters; + } + +} diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/TransformerConfigurer.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/TransformerConfigurer.java new file mode 100644 index 0000000000..7375d02f10 --- /dev/null +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/TransformerConfigurer.java @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2008 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; + +import javax.xml.transform.Transformer; + +import org.springframework.integration.core.Message; + +/** + * Allows customistation of the transformer based on the recevied message prior + * to transformation + * + * @author Jonas Partner + * + */ +public interface TransformerConfigurer { + + /** + * Callback method called by Xslt transfomer implementations after transformer is creates + * @param message + * @param transformer + */ + public void configureTransfomer(Message message, Transformer transformer); + +} diff --git a/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltHeaders.java b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltHeaders.java new file mode 100644 index 0000000000..1facb10be7 --- /dev/null +++ b/org.springframework.integration.xml/src/main/java/org/springframework/integration/xml/transformer/XsltHeaders.java @@ -0,0 +1,38 @@ +/* + * Copyright 2002-2008 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; + +import javax.xml.transform.Transformer; + +/** + * Message headers that can be used to configure the {@link Transformer} + * instance used for Xsl transformation + * + * @author Jonas Partner + * + */ +public abstract class XsltHeaders { + + public static final String PREFIX = "xslt_"; + + public static final String OUTPUT_PROPERTY = PREFIX + "output_property_"; + + public static final String PARAMATER = PREFIX + "parameter_"; + + + +} 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 a156c975d9..7667e1d8cd 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 @@ -20,6 +20,7 @@ import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Templates; +import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; @@ -29,8 +30,10 @@ import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; import org.springframework.core.io.Resource; +import org.springframework.integration.core.Message; import org.springframework.integration.core.MessagingException; import org.springframework.integration.transformer.AbstractPayloadTransformer; +import org.springframework.integration.transformer.AbstractTransformer; import org.springframework.integration.xml.result.DomResultFactory; import org.springframework.integration.xml.result.ResultFactory; import org.springframework.integration.xml.source.DomSourceFactory; @@ -64,7 +67,7 @@ import java.io.IOException; * @author Jonas Partner * @author Mark Fisher */ -public class XsltPayloadTransformer extends AbstractPayloadTransformer { +public class XsltPayloadTransformer extends AbstractTransformer { private final Templates templates; @@ -75,6 +78,8 @@ public class XsltPayloadTransformer extends AbstractPayloadTransformer message) throws Exception { + Transformer transformer = buildTransformer(message); + Object payload = message.getPayload(); Object transformedPayload = null; if (this.alwaysUseSourceResultFactories) { - transformedPayload = transformUsingFactories(payload); + transformedPayload = transformUsingFactories(payload, transformer); } else if (payload instanceof String) { - transformedPayload = transformString((String) payload); + transformedPayload = transformString((String) payload, transformer); } else if (payload instanceof Document) { - transformedPayload = transformDocument((Document) payload); + transformedPayload = transformDocument((Document) payload, transformer); } else if (payload instanceof Source) { - transformedPayload = transformSource((Source) payload, payload); + transformedPayload = transformSource((Source) payload, payload, transformer); } else { // fall back to trying factories - transformedPayload = transformUsingFactories(payload); + transformedPayload = transformUsingFactories(payload, transformer); } return transformedPayload; } - protected Object transformUsingFactories(Object payload) throws TransformerException { + protected Object transformUsingFactories(Object payload, Transformer transformer) throws TransformerException { Source source = sourceFactory.createSource(payload); - return transformSource(source, payload); + return transformSource(source, payload, transformer); } - protected Object transformSource(Source source, Object payload) throws TransformerException { + protected Object transformSource(Source source, Object payload, Transformer transformer) throws TransformerException { Result result = resultFactory.createResult(payload); - this.templates.newTransformer().transform(source, result); + transformer.transform(source, result); if (resultTransformer != null) { return resultTransformer.transformResult(result); @@ -174,14 +181,14 @@ public class XsltPayloadTransformer extends AbstractPayloadTransformer message) throws TransformerException{ + Transformer transformer = this.templates.newTransformer(); + if(this.transformerConfigurer != null){ + this.transformerConfigurer.configureTransfomer(message, transformer); + } + return transformer; + } + + } diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/DefaultTransformerConfiguerTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/DefaultTransformerConfiguerTests.java new file mode 100644 index 0000000000..a3fa949214 --- /dev/null +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/DefaultTransformerConfiguerTests.java @@ -0,0 +1,149 @@ +package org.springframework.integration.xml.transformer; + +import static org.junit.Assert.*; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import javax.xml.transform.ErrorListener; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.URIResolver; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.integration.core.Message; +import org.springframework.integration.message.MessageBuilder; + +public class DefaultTransformerConfiguerTests { + + StubTransformer transformer; + + DefaultTransformerConfigurer transformerConfigurer; + + @Before + public void setUp(){ + this.transformer = new StubTransformer(); + this.transformerConfigurer = new DefaultTransformerConfigurer(); + } + + + + @Test + public void testSettingParametersAndOutputProperties(){ + Message testMessage = MessageBuilder.withPayload("test") + .setHeader("xslt_parameter_headerOne",1) + .setHeader("xslt_parameter_headerTwo", "string") + .setHeader("xslt_output_property_outOne","1") + .setHeader("xslt_output_property_outTwo","2") + .build(); + transformerConfigurer.configureTransfomer(testMessage, transformer); + + Object paramOne = transformer.getParameter("headerOne"); + assertEquals("Wrong value for headerOne parameter",1, paramOne); + + Object paramTwo = transformer.getParameter("headerTwo"); + assertEquals("Wrong value for headerTwo parameter","string", paramTwo); + + String outPropertyOne = transformer.getOutputProperty("outOne"); + assertEquals("Wrong value for headerOne parameter","1", outPropertyOne); + + String outPropertyTwo = transformer.getOutputProperty("outTwo"); + assertEquals("Wrong value for headerTwo parameter","2", outPropertyTwo); + + + } + + @Test(expected = IllegalArgumentException.class) + public void testNonStringOutputPropertyHeader(){ + Message testMessage = MessageBuilder.withPayload("test") + .setHeader("xslt_output_property_outOne",12) + .build(); + transformerConfigurer.configureTransfomer(testMessage, transformer); + } + + private static class StubTransformer extends Transformer{ + + Map paramterMap = new HashMap(); + + Map outputProperties = new HashMap(); + + @Override + public void clearParameters() { + paramterMap.clear(); + + } + + @Override + public ErrorListener getErrorListener() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Properties getOutputProperties() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getOutputProperty(String name) + throws IllegalArgumentException { + return outputProperties.get(name); + } + + @Override + public Object getParameter(String name) { + return paramterMap.get(name); + } + + @Override + public URIResolver getURIResolver() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setErrorListener(ErrorListener listener) + throws IllegalArgumentException { + // TODO Auto-generated method stub + + } + + @Override + public void setOutputProperties(Properties oformat) { + // TODO Auto-generated method stub + + } + + @Override + public void setOutputProperty(String name, String value) + throws IllegalArgumentException { + outputProperties.put(name, value); + } + + @Override + public void setParameter(String name, Object value) { + paramterMap.put(name, value); + } + + @Override + public void setURIResolver(URIResolver resolver) { + // TODO Auto-generated method stub + + } + + @Override + public void transform(Source xmlSource, Result outputTarget) + throws TransformerException { + // TODO Auto-generated method stub + + } + + + } + +} diff --git a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java index 7fe01c0977..3a08306ce6 100644 --- a/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java +++ b/org.springframework.integration.xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java @@ -32,7 +32,9 @@ import org.w3c.dom.Document; import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ClassPathResource; +import org.springframework.integration.core.Message; import org.springframework.integration.core.MessagingException; +import org.springframework.integration.message.MessageBuilder; import org.springframework.integration.xml.util.XmlTestUtil; import org.springframework.xml.transform.StringSource; import static org.hamcrest.CoreMatchers.is; @@ -48,88 +50,92 @@ public class XsltPayloadTransformerTests { private String outputAsString = "test"; - @Before public void setUp() throws Exception { transformer = new XsltPayloadTransformer(getXslResource()); } - @Test public void testDocumentAsPayload() throws Exception { - Object transformed = transformer.transformPayload( - XmlTestUtil.getDocumentForString(docAsString)); - assertTrue("Wrong return type for document payload", - Document.class.isAssignableFrom(transformed.getClass())); + Object transformed = transformer.doTransform(buildMessage(XmlTestUtil.getDocumentForString(docAsString))); + assertTrue("Wrong return type for document payload", Document.class + .isAssignableFrom(transformed.getClass())); Document transformedDocument = (Document) transformed; - assertXMLEqual(outputAsString, XmlTestUtil.docToString(transformedDocument)); + assertXMLEqual(outputAsString, XmlTestUtil + .docToString(transformedDocument)); } @Test public void testSourceAsPayload() throws Exception { - Object transformed = transformer.transformPayload(new StringSource(docAsString)); - assertEquals("Wrong return type for source payload", - DOMResult.class, transformed.getClass()); + Object transformed = transformer.doTransform(buildMessage(new StringSource(docAsString))); + assertEquals("Wrong return type for source payload", DOMResult.class, + transformed.getClass()); DOMResult result = (DOMResult) transformed; - assertXMLEqual("Document incorrect after transformation", - XmlTestUtil.getDocumentForString(outputAsString), - (Document) result.getNode()); + assertXMLEqual("Document incorrect after transformation", XmlTestUtil + .getDocumentForString(outputAsString), (Document) result + .getNode()); } @Test public void testStringAsPayload() throws Exception { - Object transformed = transformer.transformPayload(docAsString); - assertEquals("Wrong return type for string payload", - String.class, transformed.getClass()); + Object transformed = transformer.doTransform(buildMessage(docAsString)); + assertEquals("Wrong return type for string payload", String.class, + transformed.getClass()); String transformedString = (String) transformed; - assertXMLEqual("String incorrect after transform", - outputAsString, transformedString); + assertXMLEqual("String incorrect after transform", outputAsString, + transformedString); } @Test public void testStringAsPayloadUseFactoriesTrue() throws Exception { transformer.setAlwaysUseSourceResultFactories(true); - Object transformed = transformer.transformPayload(docAsString); + Object transformed = transformer.doTransform(buildMessage(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()); + assertXMLEqual("Document incorrect after transformation", XmlTestUtil + .getDocumentForString(outputAsString), (Document) result + .getNode()); } @Test public void testSourceWithResultTransformer() throws Exception { Integer returnValue = new Integer(13); - transformer = new XsltPayloadTransformer(getXslResource(), new StubResultTransformer(returnValue)); - Object transformed = transformer.transformPayload(new StringSource(docAsString)); - assertEquals("Wrong value from result conversion", returnValue, transformed); + transformer = new XsltPayloadTransformer(getXslResource(), + new StubResultTransformer(returnValue)); + Object transformed = transformer.doTransform(buildMessage(new StringSource( + docAsString))); + assertEquals("Wrong value from result conversion", returnValue, + transformed); } @Test(expected = TransformerException.class) public void testNonXmlString() throws Exception { - transformer.transformPayload("test"); + transformer.doTransform(buildMessage("test")); } @Test(expected = MessagingException.class) public void testUnsupportedPayloadType() throws Exception { - transformer.transformPayload(new Long(12)); + transformer.doTransform(buildMessage(new Long(12))); } - @Test - public void testXsltWithImports() throws Exception { - Resource resource = new ClassPathResource("transform-with-import.xsl", this.getClass()); - transformer = new XsltPayloadTransformer(resource); - assertThat(transformer.transformString(docAsString), is(outputAsString)); - } - + @Test + public void testXsltWithImports() throws Exception { + Resource resource = new ClassPathResource("transform-with-import.xsl", + this.getClass()); + transformer = new XsltPayloadTransformer(resource); + assertEquals(transformer.doTransform(buildMessage(docAsString)), outputAsString); + } + protected Message buildMessage(Object payload){ + return MessageBuilder.withPayload(payload).build(); +} + private Resource getXslResource() throws Exception { String xsl = "test"; return new ByteArrayResource(xsl.getBytes("UTF-8")); } - public static class StubResultTransformer implements ResultTransformer { private Object objectToReturn;