8058152: JDK accepts XSLT stylesheet having import element erroneously placed
Reviewed-by: naoto, lancea
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java Tue Oct 11 17:39:31 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Parser.java Wed Oct 12 17:36:19 2016 -0700
@@ -1342,6 +1342,12 @@
}
else {
SyntaxTreeNode parent = _parentStack.peek();
+ if (element.getClass().isAssignableFrom(Import.class) &&
+ parent.notTypeOf(Import.class)) {
+ ErrorMsg err = new ErrorMsg(ErrorMsg.IMPORT_PRECEDE_OTHERS_ERR,
+ prefix+':'+localname);
+ throw new SAXException(err.toString());
+ }
parent.addElement(element);
element.setParent(parent);
}
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java Tue Oct 11 17:39:31 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java Wed Oct 12 17:36:19 2016 -0700
@@ -524,6 +524,24 @@
}
/**
+ * Checks whether any children of this node is not of the specified type.
+ *
+ * @param type the type to be checked against
+ * @return true if there is at least one child that is not of the specified
+ * type, false otherwise.
+ */
+ public boolean notTypeOf(Class<?> type) {
+ if (_contents.size() > 0) {
+ for (SyntaxTreeNode item : _contents) {
+ if (!item.getClass().isAssignableFrom(type)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* Return true if the node represents a simple RTF.
*
* A node is a simple RTF if all children only produce Text value.
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java Tue Oct 11 17:39:31 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages.java Wed Oct 12 17:36:19 2016 -0700
@@ -274,6 +274,14 @@
"Circular import/include. Stylesheet ''{0}'' already loaded."},
/*
+ * Note to translators: "xsl:import" and "xsl:include" are keywords that
+ * should not be translated.
+ */
+ {ErrorMsg.IMPORT_PRECEDE_OTHERS_ERR,
+ "The xsl:import element children must precede all other element children of "
+ + "an xsl:stylesheet element, including any xsl:include element children."},
+
+ /*
* Note to translators: A result-tree fragment is a portion of a
* resulting XML document represented as a tree. "<xsl:sort>" is a
* keyword and should not be translated.
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java Tue Oct 11 17:39:31 2016 -0700
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMsg.java Wed Oct 12 17:36:19 2016 -0700
@@ -70,6 +70,7 @@
public static final String STRAY_ATTRIBUTE_ERR = "STRAY_ATTRIBUTE_ERR";
public static final String ILLEGAL_ATTRIBUTE_ERR = "ILLEGAL_ATTRIBUTE_ERR";
public static final String CIRCULAR_INCLUDE_ERR = "CIRCULAR_INCLUDE_ERR";
+ public static final String IMPORT_PRECEDE_OTHERS_ERR = "IMPORT_PRECEDE_OTHERS_ERR";
public static final String RESULT_TREE_SORT_ERR = "RESULT_TREE_SORT_ERR";
public static final String SYMBOLS_REDEF_ERR = "SYMBOLS_REDEF_ERR";
public static final String XSL_VERSION_ERR = "XSL_VERSION_ERR";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/StylesheetTest.java Wed Oct 12 17:36:19 2016 -0700
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 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.StringReader;
+import org.xml.sax.InputSource;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.sax.SAXSource;
+import javax.xml.transform.TransformerConfigurationException;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/**
+ * @test
+ * @bug 8058152
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm -DrunSecMngr=true transform.StylesheetTest
+ * @run testng/othervm transform.StylesheetTest
+ * @summary this test contains test cases for verifying stylesheet
+ */
+@Listeners(jaxp.library.FilePolicy.class)
+public class StylesheetTest {
+
+ /**
+ * @bug 8058152
+ * Verifies that an error is reported if the xsl:import element
+ * is not at the top of the stylesheet.
+ * @throws TransformerConfigurationException
+ */
+ @Test(dataProvider = "invalidImport", expectedExceptions = TransformerConfigurationException.class)
+ public void testInvalidImport(String xsl) throws TransformerConfigurationException {
+ StringReader xsl1 = new StringReader(xsl);
+ TransformerFactory factory = TransformerFactory.newInstance();
+ SAXSource xslSource = new SAXSource(new InputSource(xsl1));
+ Transformer transformer = factory.newTransformer(xslSource);
+ }
+
+ /**
+ * @bug 8058152
+ * Verifies that valid xsl:import elements are accepted
+ * @throws TransformerConfigurationException
+ */
+ @Test(dataProvider = "validImport")
+ public void testValidImport(String file) throws TransformerConfigurationException {
+ String xsl = getClass().getResource(file).getFile();
+ TransformerFactory factory = TransformerFactory.newInstance();
+ SAXSource xslSource = new SAXSource(new InputSource(xsl));
+ Transformer transformer = factory.newTransformer(xslSource);
+ }
+
+ /*
+ DataProvider: for testing with xsl:import placed incorrectly
+ Data: stylesheet
+ */
+ @DataProvider(name = "invalidImport")
+ public Object[][] getInvalid() {
+
+ return new Object[][]{
+ // xsl:import after template and include elements
+ {"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
+ + "\n"
+ + " <xsl:template match=\"content\">\n"
+ + " <html>\n"
+ + " <xsl:apply-templates/>\n"
+ + " </html>\n"
+ + " </xsl:template>\n"
+ + " \n"
+ + " <xsl:include href=\"XSLInclude_header.xsl\"/>\n"
+ + "\n"
+ + " <xsl:template match=\"content/title\">\n"
+ + " <h1>\n"
+ + " <xsl:apply-templates/>\n"
+ + " </h1>\n"
+ + " </xsl:template>\n"
+ + " \n"
+ + " <xsl:import href=\"XSLInclude_footer.xsl\"/>\n"
+ + "\n"
+ + "</xsl:stylesheet>"},
+
+ // xsl:import inside template
+ {"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
+ + "\n"
+ + " <xsl:template match=\"content\">\n"
+ + " <xsl:import href=\"XSLInclude_header.xsl\"/>"
+ + " <html>\n"
+ + " <xsl:apply-templates/>\n"
+ + " </html>\n"
+ + " </xsl:template>\n"
+ + "\n"
+ + "</xsl:stylesheet>"},
+
+ // xsl:import after xsl:include
+ {"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
+ + " <xsl:include href=\"XSLInclude_header.xsl\"/>\n"
+ + " <xsl:import href=\"XSLInclude_footer.xsl\"/>\n"
+ + "\n"
+ + " <xsl:template match=\"content/title\">\n"
+ + " <h1>\n"
+ + " <xsl:apply-templates/>\n"
+ + " </h1>\n"
+ + " </xsl:template>\n"
+ + "\n"
+ + "</xsl:stylesheet>"}
+ };
+ }
+
+ /*
+ DataProvider: for testing with xsl:import placed correctly
+ Data: path to stylesheet
+ */
+ @DataProvider(name = "validImport")
+ public Object[][] getValid() {
+
+ return new Object[][]{
+ // xsl:import at the top
+ {"XSLInclude_main.xsl"},
+
+ // two xsl:import elements at the top
+ {"XSLImport.xsl"}
+ };
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/XSLImport.xsl Wed Oct 12 17:36:19 2016 -0700
@@ -0,0 +1,21 @@
+<?xml version="1.1" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:import href="XSLInclude_header.xsl"/>
+ <xsl:import href="XSLInclude_footer.xsl"/>
+
+ <xsl:template match="content">
+ <html>
+ <xsl:apply-templates/>
+ </html>
+ </xsl:template>
+
+ <xsl:template match="content/title">
+ <h1>
+ <xsl:apply-templates/>
+ </h1>
+ </xsl:template>
+
+
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/XSLInclude_footer.xsl Wed Oct 12 17:36:19 2016 -0700
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="footer">
+ <dv id="footer"><xsl:apply-templates/></dv>
+ </xsl:template>
+
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/XSLInclude_header.xsl Wed Oct 12 17:36:19 2016 -0700
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:template match="header">
+ <h4><xsl:apply-templates/></h4>
+ </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/transform/XSLInclude_main.xsl Wed Oct 12 17:36:19 2016 -0700
@@ -0,0 +1,20 @@
+<?xml version="1.1" encoding="UTF-8"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
+
+ <xsl:import href="XSLInclude_header.xsl"/>
+
+ <xsl:template match="content">
+ <html>
+ <xsl:apply-templates/>
+ </html>
+ </xsl:template>
+
+ <xsl:template match="content/title">
+ <h1>
+ <xsl:apply-templates/>
+ </h1>
+ </xsl:template>
+
+ <xsl:include href="XSLInclude_footer.xsl"/>
+
+</xsl:stylesheet>
\ No newline at end of file