support for setting parameters and output properties on transformer instances used by the XsltPayloadTransformer

resolves INT-897
This commit is contained in:
Jonas Partner
2010-03-11 14:16:50 +00:00
parent 2dffbf32d0
commit 4a4a867f63
6 changed files with 386 additions and 51 deletions

View File

@@ -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<String,Object> parameters = extractParameterHeaders(message.getHeaders());
for(String paramName: parameters.keySet()){
transformer.setParameter(paramName, parameters.get(paramName));
}
Map<String, String> outputProperties = extractOutputPropertyHeaders(message.getHeaders());
for(String outputPropertyName : outputProperties.keySet()){
transformer.setOutputProperty(outputPropertyName, outputProperties.get(outputPropertyName));
}
}
protected Map<String, String> extractOutputPropertyHeaders(
MessageHeaders headers) {
Map<String, String> parameters = new HashMap<String, String>();
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<String, Object> extractParameterHeaders(MessageHeaders headers) {
Map<String, Object> parameters = new HashMap<String, Object>();
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;
}
}

View File

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

View File

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

View File

@@ -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<Object, Object> {
public class XsltPayloadTransformer extends AbstractTransformer {
private final Templates templates;
@@ -75,6 +78,8 @@ public class XsltPayloadTransformer extends AbstractPayloadTransformer<Object, O
private volatile ResultFactory resultFactory = new DomResultFactory();
private volatile boolean alwaysUseSourceResultFactories = false;
private volatile TransformerConfigurer transformerConfigurer;
public XsltPayloadTransformer(Templates templates) throws ParserConfigurationException {
@@ -141,32 +146,34 @@ public class XsltPayloadTransformer extends AbstractPayloadTransformer<Object, O
this.alwaysUseSourceResultFactories = alwaysUserSourceResultFactories;
}
@Override
public Object transformPayload(Object payload) throws TransformerException {
@Override
protected Object doTransform(Message<?> 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<Object, O
return result;
}
protected String transformString(String stringPayload) throws TransformerException {
protected String transformString(String stringPayload, Transformer transformer) throws TransformerException {
StringResult result = new StringResult();
this.templates.newTransformer().transform(
transformer.transform(
new StringSource(stringPayload), result);
return result.toString();
}
protected Document transformDocument(Document documentPayload) throws TransformerException {
protected Document transformDocument(Document documentPayload, Transformer transformer) throws TransformerException {
DOMSource source = new DOMSource(documentPayload);
Result result = resultFactory.createResult(documentPayload);
if (!DOMResult.class.isAssignableFrom(result.getClass())) {
@@ -189,8 +196,19 @@ public class XsltPayloadTransformer extends AbstractPayloadTransformer<Object, O
"Document to Document conversion requires a DOMResult-producing ResultFactory implementation");
}
DOMResult domResult = (DOMResult) result;
this.templates.newTransformer().transform(source, domResult);
transformer.transform(source, domResult);
return (Document) domResult.getNode();
}
protected Transformer buildTransformer(Message<?> message) throws TransformerException{
Transformer transformer = this.templates.newTransformer();
if(this.transformerConfigurer != null){
this.transformerConfigurer.configureTransfomer(message, transformer);
}
return transformer;
}
}