blob: 87360daf486868b0ef3974ed503d618e71f96ebe [file] [log] [blame]
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package transform;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Listeners;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static jaxp.library.JAXPTestUtilities.runWithAllPerm;
import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
import static jaxp.library.JAXPTestUtilities.setSystemProperty;
import static jaxp.library.JAXPTestUtilities.getSystemProperty;
/*
* @test
* @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
* @compile DocumentExtFunc.java
* @run testng/othervm -DrunSecMngr=true transform.XSLTFunctionsTest
* @run testng/othervm transform.XSLTFunctionsTest
* @summary This class contains tests for XSLT functions.
*/
@Listeners({jaxp.library.FilePolicy.class})
public class XSLTFunctionsTest {
/**
* @bug 8165116
* Verifies that redirect works properly when extension function is enabled
*
* @param xml the XML source
* @param xsl the stylesheet that redirect output to a file
* @param output the output file
* @param redirect the redirect file
* @throws Exception if the test fails
**/
@Test(dataProvider = "redirect")
public void testRedirect(String xml, String xsl, String output, String redirect) throws Exception {
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(ORACLE_ENABLE_EXTENSION_FUNCTION, true);
Transformer t = tf.newTransformer(new StreamSource(new StringReader(xsl)));
//Transform the xml
t.transform(new StreamSource(new StringReader(xml)), new StreamResult(new StringWriter()));
// Verifies that the output is redirected successfully
String userDir = getSystemProperty("user.dir");
Path pathOutput = Paths.get(userDir, output);
Path pathRedirect = Paths.get(userDir, redirect);
Assert.assertTrue(Files.exists(pathOutput));
Assert.assertTrue(Files.exists(pathRedirect));
System.out.println("Output to " + pathOutput + " successful.");
System.out.println("Redirect to " + pathRedirect + " successful.");
Files.deleteIfExists(pathOutput);
Files.deleteIfExists(pathRedirect);
}
/**
* @bug 8161454
* Verifies that the new / correct name is supported, as is the old / incorrect
* one for compatibility
*/
@Test
public void testNameChange() {
boolean feature;
TransformerFactory tf = TransformerFactory.newInstance();
feature = tf.getFeature(ORACLE_ENABLE_EXTENSION_FUNCTION);
System.out.println("Default setting: " + feature);
// The default: true if no SecurityManager, false otherwise
Assert.assertTrue(feature == getDefault());
setSystemProperty(SP_ENABLE_EXTENSION_FUNCTION, getDefaultOpposite());
tf = TransformerFactory.newInstance();
feature = tf.getFeature(ORACLE_ENABLE_EXTENSION_FUNCTION);
System.out.println("After setting " + SP_ENABLE_EXTENSION_FUNCTION + ": " + feature);
clearSystemProperty(SP_ENABLE_EXTENSION_FUNCTION);
// old/incorrect name is still supported
Assert.assertTrue(feature != getDefault());
setSystemProperty(SP_ENABLE_EXTENSION_FUNCTION_SPEC, getDefaultOpposite());
tf = TransformerFactory.newInstance();
feature = tf.getFeature(ORACLE_ENABLE_EXTENSION_FUNCTION);
System.out.println("After setting " + SP_ENABLE_EXTENSION_FUNCTION_SPEC + ": " + feature);
clearSystemProperty(SP_ENABLE_EXTENSION_FUNCTION_SPEC);
// new/correct name is effective
Assert.assertTrue(feature != getDefault());
}
final boolean isSecure;
{
String runSecMngr = getSystemProperty("runSecMngr");
isSecure = runSecMngr != null && runSecMngr.equals("true");
}
// The default: true if no SecurityManager, false otherwise
private boolean getDefault() {
if (isSecure) {
return false;
} else {
return true;
}
}
// Gets a String value that is opposite to the default value
private String getDefaultOpposite() {
if (isSecure) {
return "true";
} else {
return "false";
}
}
/**
* @bug 8062518 8153082
* Verifies that a reference to the DTM created by XSLT document function is
* actually read from the DTM by an extension function.
* @param xml Content of xml file to process
* @param xsl stylesheet content that loads external document {@code externalDoc}
* with XSLT 'document' function and then reads it with
* DocumentExtFunc.test() function
* @param externalDoc Content of the external xml document
* @param expectedResult Expected transformation result
**/
@Test(dataProvider = "document")
public void testDocument(final String xml, final String xsl,
final String externalDoc, final String expectedResult) throws Exception {
// Prepare sources for transormation
Source src = new StreamSource(new StringReader(xml));
Source xslsrc = new StreamSource(new StringReader(xsl));
// Create factory and transformer
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(ORACLE_ENABLE_EXTENSION_FUNCTION, true);
tf.setAttribute(EXTENSION_CLASS_LOADER,
runWithAllPerm(() -> Thread.currentThread().getContextClassLoader()));
Transformer t = tf.newTransformer( xslsrc );
t.setErrorListener(tf.getErrorListener());
// Set URI Resolver to return the newly constructed xml
// stream source object from xml test string
t.setURIResolver(new URIResolver() {
@Override
public Source resolve(String href, String base)
throws TransformerException {
if (href.contains("externalDoc")) {
return new StreamSource(new StringReader(externalDoc));
} else {
return new StreamSource(new StringReader(xml));
}
}
});
// Prepare output stream
StringWriter xmlResultString = new StringWriter();
StreamResult xmlResultStream = new StreamResult(xmlResultString);
//Transform the xml
t.transform(src, xmlResultStream);
// If the document can't be accessed and the bug is in place then
// reported exception will be thrown during transformation
System.out.println("Transformation result:"+xmlResultString.toString().trim());
// Check the result - it should contain two (node name, node values) entries -
// one for original document, another for a document created with
// call to 'document' function
assertEquals(xmlResultString.toString().trim(), expectedResult);
}
@DataProvider(name = "document")
public static Object[][] documentTestData() {
return new Object[][] {
{documentTestXml, documentTestXsl, documentTestExternalDoc, documentTesteExpectedResult},
};
}
@DataProvider(name = "redirect")
public static Object[][] getData() {
return new Object[][] {
{documentTestXml, xslRedirect, "testoutput.xml", "testredirect.xml"},
};
}
static final String documentTestXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Test>Doc</Test>";
static final String documentTestExternalDoc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Test>External Doc</Test>";
static final String documentTestXsl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<xsl:transform version=\"1.0\""
+ " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" "
+ " xmlns:cfunc=\"http://xml.apache.org/xalan/java/\">"
+ "<xsl:template match=\"/\">"
+ "<xsl:element name=\"root\">"
+ "<xsl:variable name=\"other_doc\" select=\"document(&#39;externalDoc&#39;)\"/>"
+ "<!-- Source -->"
+ "<xsl:value-of select=\"cfunc:transform.DocumentExtFunc.test(/Test)\"/>"
+ "<!-- document() -->"
+ "<xsl:value-of select=\"cfunc:transform.DocumentExtFunc.test($other_doc/Test)\"/>"
+ "</xsl:element></xsl:template></xsl:transform>";
static final String documentTesteExpectedResult = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ "<root>[Test:Doc][Test:External Doc]</root>";
static String xslRedirect = " <xsl:stylesheet \n"
+ " xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\"\n"
+ " xmlns:xsltc=\"http://xml.apache.org/xalan/xsltc\"\n"
+ " xmlns:redirect=\"http://xml.apache.org/xalan/redirect\"\n"
+ " extension-element-prefixes=\"xsltc redirect\"\n"
+ " version=\"1.0\">\n"
+ " <xsl:template match=\"/\">\n"
+ " <xsl:text>This goes to standard output</xsl:text>\n"
+ " <xsltc:output file=\"testoutput.xml\">\n"
+ " <xsl:text>This ends up in the file 'testoutput.xml'</xsl:text>\n"
+ " </xsltc:output>\n"
+ " <redirect:write file=\"testredirect.xml\">\n"
+ " <xsl:text>This ends up in the file 'testredirect.xml'</xsl:text>\n"
+ " </redirect:write>\n"
+ " </xsl:template>\n"
+ "</xsl:stylesheet>";
public static final String ORACLE_JAXP_PROPERTY_PREFIX =
"http://www.oracle.com/xml/jaxp/properties/";
/**
* Feature enableExtensionFunctions
*/
public static final String ORACLE_ENABLE_EXTENSION_FUNCTION =
ORACLE_JAXP_PROPERTY_PREFIX + "enableExtensionFunctions";
static final String SP_ENABLE_EXTENSION_FUNCTION = "javax.xml.enableExtensionFunctions";
// This is the correct name by the spec
static final String SP_ENABLE_EXTENSION_FUNCTION_SPEC = "jdk.xml.enableExtensionFunctions";
private static final String EXTENSION_CLASS_LOADER = "jdk.xml.transform.extensionClassLoader";
}