diff --git a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java index 205c8f3013..368bb7a231 100644 --- a/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java +++ b/spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 the original author or authors. + * Copyright 2002-2011 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. @@ -32,6 +32,9 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + +import org.w3c.dom.Document; + import org.springframework.context.expression.MapAccessor; import org.springframework.core.io.Resource; import org.springframework.expression.Expression; @@ -49,7 +52,6 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.PatternMatchUtils; import org.springframework.xml.transform.StringResult; import org.springframework.xml.transform.StringSource; -import org.w3c.dom.Document; /** * Thread safe XSLT transformer implementation which returns a transformed @@ -70,223 +72,234 @@ import org.w3c.dom.Document; * 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 * @author Oleg Zhurakousky */ public class XsltPayloadTransformer extends AbstractTransformer { - private final Log logger = LogFactory.getLog(this.getClass()); + private final Log logger = LogFactory.getLog(this.getClass()); - private final Templates templates; + private final Templates templates; - private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); - private Map xslParameterMappings; + private Map xslParameterMappings; - 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 alwaysUseSourceFactory = false; + private volatile boolean alwaysUseSourceFactory = false; - private volatile boolean alwaysUseResultFactory = false; + private volatile boolean alwaysUseResultFactory = false; - private volatile String[] xsltParamHeaders; + private volatile String[] xsltParamHeaders; - public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException { - this(templates, null); - } + public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException { + this(templates, null); + } - public XsltPayloadTransformer(Resource xslResource) throws Exception { - this(TransformerFactory.newInstance().newTemplates(createStreamSourceOnResource(xslResource)), 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(createStreamSourceOnResource(xslResource)), resultTransformer); - } + public XsltPayloadTransformer(Resource xslResource, ResultTransformer resultTransformer) throws Exception { + this(TransformerFactory.newInstance().newTemplates( + createStreamSourceOnResource(xslResource)), resultTransformer); + } - public XsltPayloadTransformer(Templates templates, ResultTransformer resultTransformer) throws ParserConfigurationException { - this.templates = templates; - this.resultTransformer = resultTransformer; - this.evaluationContext.addPropertyAccessor(new MapAccessor()); - } + public XsltPayloadTransformer(Templates templates, ResultTransformer resultTransformer) throws ParserConfigurationException { + this.templates = templates; + this.resultTransformer = resultTransformer; + this.evaluationContext.addPropertyAccessor(new MapAccessor()); + } - /** - * Sets the SourceFactory. - */ - public void setSourceFactory(SourceFactory sourceFactory) { - Assert.notNull(sourceFactory, "SourceFactory must not be null"); - this.sourceFactory = sourceFactory; - } + /** + * Sets the SourceFactory. + */ + public void setSourceFactory(SourceFactory sourceFactory) { + Assert.notNull(sourceFactory, "SourceFactory must not be null"); + this.sourceFactory = sourceFactory; + } - /** - * Sets the ResultFactory - */ - public void setResultFactory(ResultFactory resultFactory) { - Assert.notNull(sourceFactory, "ResultFactory must not be null"); - this.resultFactory = resultFactory; - } + /** + * Sets the ResultFactory + */ + public void setResultFactory(ResultFactory resultFactory) { + Assert.notNull(sourceFactory, "ResultFactory must not be null"); + this.resultFactory = resultFactory; + } + + /** + * Specify whether to always use source factory even for directly supported payload types. + */ + public void setAlwaysUseSourceFactory(boolean alwaysUseSourceFactory) { + this.alwaysUseSourceFactory = alwaysUseSourceFactory; + } + + /** + * Specify whether to always use result factory even for directly supported payload types + */ + public void setAlwaysUseResultFactory(boolean alwaysUseResultFactory) { + this.alwaysUseResultFactory = alwaysUseResultFactory; + } + + public void setXslParameterMappings(Map xslParameterMappings) { + this.xslParameterMappings = xslParameterMappings; + } + + public void setXsltParamHeaders(String[] xsltParamHeaders) { + this.xsltParamHeaders = xsltParamHeaders; + } + + public String getComponentType() { + return "xml:xslt-transformer"; + } + + @Override + protected Object doTransform(Message message) throws Exception { + Transformer transformer = buildTransformer(message); + Object payload; + if (this.alwaysUseSourceFactory) { + payload = sourceFactory.createSource(message.getPayload()); + } + else { + payload = message.getPayload(); + } + Object transformedPayload = null; + if (this.alwaysUseResultFactory) { + transformedPayload = transformUsingResultFactory(payload, transformer); + } + else if (payload instanceof String) { + transformedPayload = transformString((String) payload, transformer); + } + else if (payload instanceof Document) { + transformedPayload = transformDocument((Document) payload, transformer); + } + else if (payload instanceof Source) { + transformedPayload = transformSource((Source) payload, payload, transformer); + } + else { + // fall back to trying factories + transformedPayload = transformUsingResultFactory(payload, transformer); + } + return transformedPayload; + } + + private Object transformUsingResultFactory(Object payload, Transformer transformer) throws TransformerException { + Source source; + if (this.alwaysUseSourceFactory) { + source = this.sourceFactory.createSource(payload); + } + else if (payload instanceof String) { + source = new StringSource((String) payload); + } + else if (payload instanceof Document) { + source = new DOMSource((Document) payload); + } + else if (payload instanceof Source) { + source = (Source) payload; + } + else { + source = this.sourceFactory.createSource(payload); + } + return transformSource(source, payload, transformer); + } + + private Object transformSource(Source source, Object payload, Transformer transformer) throws TransformerException { + Result result = this.resultFactory.createResult(payload); + transformer.transform(source, result); + if (this.resultTransformer != null) { + return this.resultTransformer.transformResult(result); + } + return result; + } + + private String transformString(String stringPayload, Transformer transformer) throws TransformerException { + StringResult result = new StringResult(); + Source source; + if (this.alwaysUseSourceFactory) { + source = this.sourceFactory.createSource(stringPayload); + } + else { + source = new StringSource(stringPayload); + } + transformer.transform(source, result); + return result.toString(); + } + + private Document transformDocument(Document documentPayload, Transformer transformer) throws TransformerException { + Source source; + if (this.alwaysUseSourceFactory) { + source = this.sourceFactory.createSource(documentPayload); + } + else { + source = new DOMSource(documentPayload); + } + Result result = this.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; + transformer.transform(source, domResult); + return (Document) domResult.getNode(); + } + + private Transformer buildTransformer(Message message) throws TransformerException { + // process individual mappings + Transformer transformer = this.templates.newTransformer(); + if (this.xslParameterMappings != null) { + for (String parameterName : this.xslParameterMappings.keySet()) { + Expression expression = this.xslParameterMappings.get(parameterName); + try { + Object value = expression.getValue(this.evaluationContext, message); + transformer.setParameter(parameterName, value); + } + catch (Exception e) { + if (logger.isWarnEnabled()) { + logger.warn("Evaluation of header expression '" + + expression.getExpressionString() + + "' failed. The XSLT parameter '" + + parameterName + "' will be skipped."); + } + } + } + } + // process xslt-parameter-headers + MessageHeaders headers = message.getHeaders(); + if (!ObjectUtils.isEmpty(this.xsltParamHeaders)) { + for (String headerName : headers.keySet()) { + if (PatternMatchUtils.simpleMatch(this.xsltParamHeaders, headerName)) { + transformer.setParameter(headerName, headers.get(headerName)); + } + } + } + return transformer; + } - /** - * User source factory even for directly supported payloads - */ - public void setAlwaysUseSourceFactory(boolean alwaysUseSourceFactory) { - this.alwaysUseSourceFactory = alwaysUseSourceFactory; - } - - - /** - * Always use result factory even for directly supported payload types - * - * @param alwaysUseResultFactory - */ - public void setAlwaysUseResultFactory(boolean alwaysUseResultFactory) { - this.alwaysUseResultFactory = alwaysUseResultFactory; - } - - public void setXslParameterMappings(Map xslParameterMappings) { - this.xslParameterMappings = xslParameterMappings; - } - - public void setXsltParamHeaders(String[] xsltParamHeaders) { - this.xsltParamHeaders = xsltParamHeaders; - } - - public String getComponentType() { - return "xml:xslt-transformer"; - } - - @Override - protected Object doTransform(Message message) throws Exception { - Transformer transformer = buildTransformer(message); - Object payload; - if (this.alwaysUseSourceFactory) { - payload = sourceFactory.createSource(message.getPayload()); - } else { - payload = message.getPayload(); - } - - - Object transformedPayload = null; - if (this.alwaysUseResultFactory) { - transformedPayload = transformUsingResultFactory(payload, transformer); - } else if (payload instanceof String) { - transformedPayload = transformString((String) payload, transformer); - } else if (payload instanceof Document) { - transformedPayload = transformDocument((Document) payload, transformer); - } else if (payload instanceof Source) { - transformedPayload = transformSource((Source) payload, payload, transformer); - } else { - // fall back to trying factories - transformedPayload = transformUsingResultFactory(payload, transformer); - } - return transformedPayload; - } - - private Object transformUsingResultFactory(Object payload, Transformer transformer) throws TransformerException { - Source source; - if (this.alwaysUseSourceFactory) { - source = this.sourceFactory.createSource(payload); - } else if (payload instanceof String) { - source = new StringSource((String) payload); - } else if (payload instanceof Document) { - source = new DOMSource((Document) payload); - } else if (payload instanceof Source) { - source = (Source) payload; - } else { - source = this.sourceFactory.createSource(payload); - } - return transformSource(source, payload, transformer); - } - - private Object transformSource(Source source, Object payload, Transformer transformer) throws TransformerException { - Result result = this.resultFactory.createResult(payload); - transformer.transform(source, result); - if (this.resultTransformer != null) { - return this.resultTransformer.transformResult(result); - } - return result; - } - - private String transformString(String stringPayload, Transformer transformer) throws TransformerException { - StringResult result = new StringResult(); - Source source; - if (this.alwaysUseSourceFactory) { - source = this.sourceFactory.createSource(stringPayload); - } else { - source = new StringSource(stringPayload); - } - transformer.transform(source, result); - return result.toString(); - } - - private Document transformDocument(Document documentPayload, Transformer transformer) throws TransformerException { - Source source; - if (this.alwaysUseSourceFactory) { - source = this.sourceFactory.createSource(documentPayload); - } else { - source = new DOMSource(documentPayload); - } - Result result = this.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; - transformer.transform(source, domResult); - return (Document) domResult.getNode(); - } - - private Transformer buildTransformer(Message message) throws TransformerException { - //process individual mappings - Transformer transformer = this.templates.newTransformer(); - if (this.xslParameterMappings != null) { - for (String parameterName : this.xslParameterMappings.keySet()) { - Expression expression = this.xslParameterMappings.get(parameterName); - try { - Object value = expression.getValue(this.evaluationContext, message); - transformer.setParameter(parameterName, value); - } catch (Exception e) { - if (logger.isWarnEnabled()) { - logger.warn("Evaluation of header expression '" + expression.getExpressionString() + - "' failed. The XSLT parameter '" + parameterName + "' will be skipped."); - } - } - } - } - // process xslt-parameter-headers - MessageHeaders headers = message.getHeaders(); - if (!ObjectUtils.isEmpty(this.xsltParamHeaders)) { - for (String headerName : headers.keySet()) { - if (PatternMatchUtils.simpleMatch(this.xsltParamHeaders, headerName)) { - transformer.setParameter(headerName, headers.get(headerName)); - } - } - } - return transformer; - } - - - /** - * Compensate for the fact that a Resource may 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()); - } - } + /** + * Compensate for the fact that a Resource may 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()); + } + } }