Here's a very basic content filter, based on XSL
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.soa.esb.actions.AbstractActionPipelineProcessor;
import org.jboss.soa.esb.actions.ActionProcessingException;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import XSLTransformer;
/**
* Simple ActionProcessor that runs a XSL transformation on the input message
*
* The advantages of relying on 'native' XSL versus using the Smooks
* transformation engine is one of size: In order to support its fragment based
* transformation, Smooks will read everything into a DOM and do transformations
* based on that.
*
* This action expects input in DEFAULT_LOCATION and also places its output
* there
*
* @author runmol
*
*/
public class XSLActionProcessor extends AbstractActionPipelineProcessor {
private static final Log LOG = LogFactory.getLog(XSLActionProcessor.class);
private static Map<String, String> cache = new HashMap<String, String>();
private String xsl;
private MessagePayloadProxy payloadProxy;
public XSLActionProcessor(ConfigTree configTree) {
xsl = configTree.getAttribute("xsl");
payloadProxy = new MessagePayloadProxy(configTree);
}
public Message process(Message message) throws ActionProcessingException {
try {
// actual processing delegated to XSLTransformer class
XSLTransformer transformer = new XSLTransformer();
byte[] bytes = (byte[]) payloadProxy.getPayload(message);
ByteArrayInputStream input = new ByteArrayInputStream(bytes);
ByteArrayOutputStream output = (ByteArrayOutputStream) transformer
.transform(input, getStylesheet(xsl));
payloadProxy.setPayload(message, output.toByteArray());
return message;
} catch (Exception e) {
throw new ActionProcessingException(e);
}
}
/**
* Loads a stylesheet from cache or from a file
*
* @return
* @throws IOException
*/
private String getStylesheet(String stylesheetFileName) throws IOException {
String result = null;
synchronized (cache) {
result = cache.get(stylesheetFileName);
if (result == null) {
LOG.info("Loading stylesheet from file " + stylesheetFileName);
InputStream in = this.getClass().getClassLoader()
.getResourceAsStream(xsl);
StringBuilder sb = new StringBuilder();
BufferedReader buf = new BufferedReader(new InputStreamReader(
in));
String line;
while ((line = buf.readLine()) != null) {
sb.append(line);
}
in.close();
result = sb.toString();
cache.put(stylesheetFileName, result);
} else {
LOG.info("Stylesheet retrieved from cache");
}
return result;
}
}
}
-
And here is the XSLTransformer class:
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
/**
* XSL transformer action on the ESB
* @author runmol
*
*/
public class XSLTransformer {
private static TransformerFactory tf = TransformerFactory.newInstance();
/**
* Runs a XSL transformation
*
* @param input stream of input data
* @param xsl XSL stylesheet (not a filename, but the actual stylesheet
* @return The transformed data
* @throws TransformerException
*/
public OutputStream transform(InputStream input,
String xsl) throws TransformerException {
if (input == null || xsl == null)
throw new IllegalArgumentException("input cannot be null");
Transformer t = tf.newTransformer(new StreamSource(
new StringReader(xsl)));
ByteArrayOutputStream output = new ByteArrayOutputStream(4096);
t.transform(new StreamSource(input), new StreamResult(output));
return output;
}
}
-
Example configuration:
<action name="ContentFilter" class="x.y.z.XSLActionProcessor"> <property name="xsl" value="cancelledfilter.xsl"></property> </action>
-
And finally here's the stylesheet used in the example. The objective is to filter out all element with the value 'true'
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sd="http://www.cph.dk/sap/sd/v1-0"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"></xsl:apply-templates> </xsl:copy> </xsl:template> <xsl:template match="sd:operation[sd:cancelled='true']"></xsl:template> </xsl:stylesheet>
Comments