/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.synapse.mediators.transform;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.axiom.om.*;
import org.apache.axis2.transport.base.BaseConstants;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseException;
import org.apache.synapse.TestMessageContextBuilder;
import org.apache.synapse.mediators.Value;
import org.apache.synapse.util.jaxp.*;
import org.apache.synapse.util.xpath.SynapseXPath;
import javax.xml.namespace.QName;
import javax.xml.transform.TransformerFactory;
public class XSLTMediatorTest extends TestCase {
private static final Class[] sourceBuilderFactories = {
DOOMSourceBuilderFactory.class,
StreamSourceBuilderFactory.class,
AXIOMSourceBuilderFactory.class };
private static final Class[] resultBuilderFactories = {
DOOMResultBuilderFactory.class,
StreamResultBuilderFactory.class,
AXIOMResultBuilderFactory.class };
private static final String SOURCE =
"<m0:CheckPriceRequest xmlns:m0=\"http://services.samples/xsd\">\n" +
"<m0:Code>String</m0:Code>\n" +
"</m0:CheckPriceRequest>";
private static final String ENCLOSING_SOURCE =
"<m:someOtherElement xmlns:m=\"http://someother\">" +
SOURCE +
"</m:someOtherElement>";
private static final String SOURCE_DYNAMIC_KEY1 =
"<m0:CheckPriceRequest xmlns:m0=\"http://services.samples/xsd\">\n" +
"<m0:DynamicXsltKey1>DynamicXsltKey1</m0:DynamicXsltKey1>\n" +
"</m0:CheckPriceRequest>\n" ;
private static final String SOURCE_DYNAMIC_KEY2 =
"<m0:CheckPriceRequest xmlns:m0=\"http://services.samples/xsd\">\n" +
"<m0:DynamicXsltKey2>DynamicXsltKey2</m0:DynamicXsltKey2>\n" +
"</m0:CheckPriceRequest>\n" ;
private static final String SOURCE_STATIC_KEY =
"<m0:CheckPriceRequest xmlns:m0=\"http://services.samples/xsd\">\n" +
"<m0:StaticXsltKey>StaticXsltKey</m0:StaticXsltKey>\n" +
"</m0:CheckPriceRequest>\n" ;
// Create the test cases for the various transformer factories, source builders and
// result builders dynamically:
public static TestSuite suite() {
TestSuite suite = new TestSuite(XSLTMediatorTest.class);
addGenericTests(suite, "Xalan", org.apache.xalan.processor.TransformerFactoryImpl.class);
addGenericTests(suite, "Saxon", net.sf.saxon.TransformerFactoryImpl.class);
return suite;
}
private static void addGenericTests(TestSuite suite, final String processorName,
final Class<? extends TransformerFactory> transformerFactoryClass) {
for (final Class sbf : sourceBuilderFactories) {
for (final Class rbf : resultBuilderFactories) {
String testName = "test" + processorName + shortName(sbf) + shortName(rbf);
suite.addTest(new TestCase(testName) {
@Override
public void runTest() throws Throwable {
String oldTransformerFactory =
TransformerFactory.newInstance().getClass().getName();
System.setProperty(TransformerFactory.class.getName(),
transformerFactoryClass.getName());
test(sbf, rbf);
System.setProperty(TransformerFactory.class.getName(),
oldTransformerFactory);
}
});
}
}
}
private static String shortName(Class clazz) {
String name = clazz.getName();
name = name.substring(name.lastIndexOf('.')+1);
if (name.endsWith("BuilderFactory")) {
name = name.substring(0, name.length()-14);
}
return name;
}
/**
* Check that the provided element is the result of the XSL transformation of
* SOURCE by the stylesheet transform_unittest.xslt.
*
* @param node result of the XSLT to be matched
*/
private void assertQuoteElement(OMNode node) {
assertTrue(node instanceof OMElement);
OMElement element = (OMElement)node;
assertTrue("GetQuote".equals(element.getLocalName()));
assertTrue("http://www.webserviceX.NET/".equals(element.getNamespace().getNamespaceURI()));
OMElement symbolElem = element.getFirstElement();
assertTrue("symbol".equals(symbolElem.getLocalName()));
assertTrue("http://www.webserviceX.NET/".equals(
symbolElem.getNamespace().getNamespaceURI()));
assertTrue("String".equals(symbolElem.getText()));
}
public void testTransformXSLTCustomSource() throws Exception {
// create a new XSLT mediator
XSLTMediator transformMediator = new XSLTMediator();
// set xpath condition to select source
SynapseXPath xpath = new SynapseXPath("//m0:CheckPriceRequest");
xpath.addNamespace("m0", "http://services.samples/xsd");
transformMediator.setSource(xpath);
// set XSLT transformation URL
setXsltTransformationURL(transformMediator, "xslt-key");
MessageContext synCtx = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/transform_unittest.xslt")
.setBodyFromString(SOURCE).addTextAroundBody().build();
transformMediator.mediate(synCtx);
// validate result
assertQuoteElement(synCtx.getEnvelope().getBody().getFirstOMChild().getNextOMSibling());
}
/**
* If a source element for transformation is not found, default to soap body
* @throws Exception if there is an error in test
*/
public void testTransformXSLTDefaultSource() throws Exception {
// create a new xslt mediator
XSLTMediator transformMediator = new XSLTMediator();
// set XSLT transformation URL
setXsltTransformationURL(transformMediator, "xslt-key");
MessageContext synCtx = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/transform_unittest.xslt")
.setBodyFromString(SOURCE).addTextAroundBody().build();
transformMediator.mediate(synCtx);
// validate result
assertQuoteElement(synCtx.getEnvelope().getBody().getFirstOMChild().getNextOMSibling());
}
public void testTransformXSLTLargeMessagesCSV() throws Exception {
// create a new switch mediator
XSLTMediator transformMediator = new XSLTMediator();
// set XSLT transformation URL
setXsltTransformationURL(transformMediator, "xslt-key");
for (int i=0; i<2; i++) {
// invoke transformation, with static enveope
MessageContext synCtx = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/transform_load.xml")
.setBodyFromFile("../../repository/conf/sample/resources/transform/message.xml")
.addTextAroundBody().build();
//MessageContext synCtx = TestUtils.getTestContextForXSLTMediator(SOURCE, props);
transformMediator.mediate(synCtx);
// synCtx.getEnvelope().serializeAndConsume(new FileOutputStream("/tmp/out.xml"));
// System.gc();
// System.out.println("done : " + i + " :: " + Runtime.getRuntime().freeMemory());
}
}
public void testTransformXSLTLargeMessagesXML() throws Exception {
// create a new switch mediator
XSLTMediator transformMediator = new XSLTMediator();
// set XSLT transformation URL
setXsltTransformationURL(transformMediator, "xslt-key");
for (int i=0; i<2; i++) {
// invoke transformation, with static enveope
MessageContext synCtx = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/transform_load_3.xml")
.setBodyFromFile("../../repository/conf/sample/resources/transform/message.xml")
.addTextAroundBody().build();
//MessageContext synCtx = TestUtils.getTestContextForXSLTMediator(SOURCE, props);
transformMediator.mediate(synCtx);
// System.gc();
// System.out.println("done : " + i + " :: " + Runtime.getRuntime().freeMemory());
}
}
public void testSynapse242() throws Exception {
// create a new switch mediator
XSLTMediator transformMediator = new XSLTMediator();
// set XSLT transformation URL
setXsltTransformationURL(transformMediator, "xslt-key");
// invoke transformation, with static enveope
MessageContext synCtx = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/transform_load_2.xml")
.setBodyFromFile("../../repository/conf/sample/resources/transform/med_message.xml")
.addTextAroundBody().build();
transformMediator.mediate(synCtx);
// validate result
OMContainer body = synCtx.getEnvelope().getBody();
assertTrue(body.getFirstOMChild().getNextOMSibling() instanceof OMElement);
assertTrue(((OMElement) body.getFirstOMChild().getNextOMSibling()).getText().length() > 0);
}
public void testTransformXSLTSmallMessages() throws Exception {
// create a new switch mediator
XSLTMediator transformMediator = new XSLTMediator();
// set XSLT transformation URL
setXsltTransformationURL(transformMediator, "xslt-key");
for (int i=0; i<5; i++) {
// invoke transformation, with static enveope
MessageContext synCtx = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/transform_load_2.xml")
.setBodyFromFile("../../repository/conf/sample/resources/transform/small_message.xml")
.addTextAroundBody().build();
//MessageContext synCtx = TestUtils.getTestContextForXSLTMediator(SOURCE, props);
transformMediator.mediate(synCtx);
//System.out.println("done : " + i + " :: " + Runtime.getRuntime().freeMemory());
}
}
public void testTransformXSLTCustomSourceNonMainElement() throws Exception {
// create a new switch mediator
XSLTMediator transformMediator = new XSLTMediator();
// set xpath condition to select source
SynapseXPath xpath = new SynapseXPath("//m0:CheckPriceRequest");
xpath.addNamespace("m0", "http://services.samples/xsd");
transformMediator.setSource(xpath);
// set XSLT transformation URL
setXsltTransformationURL(transformMediator, "xslt-key");
// invoke transformation, with static enveope
MessageContext synCtx = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/transform_unittest.xslt")
.setBodyFromString(ENCLOSING_SOURCE)
.addTextAroundBody().build();
transformMediator.mediate(synCtx);
// validate result
OMContainer body = synCtx.getEnvelope().getBody();
if (body.getFirstOMChild().getNextOMSibling() instanceof OMElement) {
OMElement someOtherElem = (OMElement) body.getFirstOMChild().getNextOMSibling();
assertTrue("someOtherElement".equals(someOtherElem.getLocalName()));
assertTrue("http://someother".equals(someOtherElem.getNamespace().getNamespaceURI()));
assertQuoteElement(someOtherElem.getFirstOMChild());
} else {
fail("Unexpected element found in SOAP body");
}
}
public void testTextEncoding() throws Exception {
XSLTMediator transformMediator = new XSLTMediator();
setXsltTransformationURL(transformMediator, "xslt-key");
MessageContext mc = new TestMessageContextBuilder().addFileEntry("xslt-key",
"../../repository/conf/sample/resources/transform/encoding_test.xslt")
.setEnvelopeFromFile("../../repository/conf/sample/resources/transform" +
"/encoding_test.xml").build();
transformMediator.mediate(mc);
OMElement resultElement = mc.getEnvelope().getBody().getFirstElement();
assertEquals(BaseConstants.DEFAULT_TEXT_WRAPPER, resultElement.getQName());
assertEquals("\u00e0 peine arriv\u00e9s nous entr\u00e2mes dans sa chambre",
resultElement.getText());
}
// Test for SYNAPSE-307
public void testInvalidStylesheet() throws Exception {
XSLTMediator transformMediator = new XSLTMediator();
setXsltTransformationURL(transformMediator, "xslt-key");
MessageContext mc = new TestMessageContextBuilder()
.addEntry("xslt-key", getClass().getResource("invalid.xslt"))
.setBodyFromString("<root/>")
.build();
try {
transformMediator.mediate(mc);
fail("Expected a SynapseException to be thrown");
} catch (SynapseException ex) {
// this is what is expected
}
}
/**
* Test that the XSLT mediator is able to handle CDATA sections in the
* source AXIOM tree.
* This tests for regression against WSCOMMONS-338. It should work with
* AXIOM versions above 1.2.7.
*
* @throws Exception in case of an error in tests
*/
public void testWithCDATA() throws Exception {
XSLTMediator transformMediator = new XSLTMediator();
setXsltTransformationURL(transformMediator, "xslt-key");
MessageContext mc = new TestMessageContextBuilder()
.addEntry("xslt-key", getClass().getResource("cdata.xslt"))
.build();
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement in = factory.createOMElement(new QName(null, "in"));
factory.createOMText(in, "test", OMNode.CDATA_SECTION_NODE);
mc.getEnvelope().getBody().addChild(in);
transformMediator.mediate(mc);
OMElement out = mc.getEnvelope().getBody().getFirstElement();
assertEquals("out", out.getLocalName());
assertEquals("test", out.getText());
}
/**
* Test that the XSLT mediator is able to handle dynamic keys
* Xpath expression can be used to generate real key dynamically
* Multiple xslt files can be loaded
*
* @throws Exception Exception in case of an error in tests
*/
public void testWithStaticDynamicKeys() throws Exception {
for (int i = 0; i < 3; i++) {
testMultipleKeys(i);
}
}
/**
* Test with multiple keys including static and dynamic keys
*
* @param num number from 0 to 2
* @throws Exception Exception in case of an error in tests
*/
private void testMultipleKeys(int num) throws Exception {
String xsltKeyValue = null;
String path;
SynapseXPath xpath;
Value xsltKey;
XSLTMediator transformMediator = new XSLTMediator();
//default source, xsltFile, and state of key (dynamic or static)
String source = "";
String xsltFile = "";
boolean isDynamicKey = true;
// based on source, different XSLTFiles can be used
if (num == 0) {
source = SOURCE_STATIC_KEY;
xsltFile = "static_key.xslt";
xsltKeyValue = "StaticXsltKey";
isDynamicKey = false;
} else if (num == 1) {
source = SOURCE_DYNAMIC_KEY1;
xsltFile = "dynamic_key_1.xslt";
xsltKeyValue = "DynamicXsltKey1";
isDynamicKey = true;
} else if (num == 2) {
source = SOURCE_DYNAMIC_KEY2;
xsltFile = "dynamic_key_2.xslt";
xsltKeyValue = "DynamicXsltKey2";
isDynamicKey = true;
}
if (isDynamicKey) {
path = "//m0:CheckPriceRequest/m0:" + xsltKeyValue;
xpath = new SynapseXPath(path);
xpath.addNamespace("m0", "http://services.samples/xsd");
// Create key from dynamic key (xpath)
xsltKey = new Value(xpath);
// set XSLT transformation URL (Xpath)
transformMediator.setXsltKey(xsltKey);
} else {
//static key
path = xsltKeyValue;
// set XSLT transformation URL (static)
setXsltTransformationURL(transformMediator, path);
}
// Mediate twice for synCtx
MessageContext synCtx = new TestMessageContextBuilder().addEntry(
xsltKeyValue, getClass().getResource(xsltFile)).setBodyFromString(
source).addTextAroundBody().build();
transformMediator.mediate(synCtx);
synCtx = new TestMessageContextBuilder().addEntry(
xsltKeyValue, getClass().getResource(xsltFile)).setBodyFromString(
source).addTextAroundBody().build();
transformMediator.mediate(synCtx);
}
protected static void test(Class sbf, Class rbf) throws Exception {
XSLTMediator transformMediator = new XSLTMediator();
Value xsltKey = new Value("xslt-key");
transformMediator.setXsltKey(xsltKey);
MessageContext mc = new TestMessageContextBuilder()
.addEntry("xslt-key", XSLTMediator.class.getResource("identity.xslt"))
.build();
OMFactory factory = OMAbstractFactory.getOMFactory();
OMElement orgRoot = factory.createOMElement(new QName("root"));
OMElement orgElement = factory.createOMElement(new QName("urn:mynamespace", "element1"));
orgElement.setText("test");
OMAttribute orgAttribute = orgElement.addAttribute("att", "testValue", null);
orgRoot.addChild(orgElement);
mc.getEnvelope().getBody().addChild(orgRoot);
transformMediator.addAttribute(XSLTMediator.SOURCE_BUILDER_FACTORY, sbf.getName());
transformMediator.addAttribute(XSLTMediator.RESULT_BUILDER_FACTORY, rbf.getName());
transformMediator.mediate(mc);
OMElement root = mc.getEnvelope().getBody().getFirstElement();
assertEquals(orgRoot.getQName(), root.getQName());
OMElement element = (OMElement)root.getFirstOMChild();
assertEquals(orgElement.getQName(), element.getQName());
assertEquals(orgElement.getText(), element.getText());
assertEquals(orgAttribute, orgElement.getAttribute(orgAttribute.getQName()));
assertNull(element.getNextOMSibling());
}
/**
* Set XSLT transformation URL
*
* @param transformMediator Mediator which need to set key
* @param xsltKeyValue String key value (static key) to set as a key
*/
private void setXsltTransformationURL(XSLTMediator transformMediator, String xsltKeyValue) {
Value xsltKey = new Value(xsltKeyValue);
transformMediator.setXsltKey(xsltKey);
}
}