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