OpenJDK / amber / amber
changeset 57312:0e1bc587472c
8176447: javax.xml.validation.Validator validates incorrectly on uniqueness constraint
Reviewed-by: lancea
author | joehw |
---|---|
date | Tue, 16 Jul 2019 21:12:14 +0000 |
parents | 065142ace8e9 |
children | 8c5c9d86e1d6 |
files | src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/identity/XPathMatcher.java test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447a.xml test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447a.xsd test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447b.xml test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447b.xsd |
diffstat | 6 files changed, 148 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/identity/XPathMatcher.java Tue Jul 16 17:50:54 2019 +0200 +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/identity/XPathMatcher.java Tue Jul 16 21:12:14 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -37,6 +37,7 @@ * @xerces.internal * * @author Andy Clark, IBM + * @LastModified: July 2019 * */ public class XPathMatcher { @@ -88,25 +89,25 @@ // /** XPath location path. */ - private XPath.LocationPath[] fLocationPaths; + private final XPath.LocationPath[] fLocationPaths; /** True if XPath has been matched. */ - private int[] fMatched; + private final int[] fMatched; /** The matching string. */ protected Object fMatchedString; /** Integer stack of step indexes. */ - private IntStack[] fStepIndexes; + private final IntStack[] fStepIndexes; /** Current step. */ - private int[] fCurrentStep; + private final int[] fCurrentStep; /** * No match depth. The value of this field will be zero while * matching is successful for the given xpath expression. */ - private int [] fNoMatchDepth; + private final int [] fNoMatchDepth; final QName fQName = new QName(); @@ -207,7 +208,7 @@ * * @throws SAXException Thrown by handler to signal an error. */ - public void startElement(QName element, XMLAttributes attributes){ + public void startElement(QName element, XMLAttributes attributes) { if (DEBUG_METHODS2) { System.out.println(toString()+"#startElement("+ "element={"+element+"},"+ @@ -215,7 +216,7 @@ ")"); } - for(int i = 0; i < fLocationPaths.length; i++) { + for (int i = 0; i < fLocationPaths.length; i++) { // push context int startStep = fCurrentStep[i]; fStepIndexes[i].push(startStep); @@ -284,18 +285,16 @@ if (DEBUG_MATCH) { System.out.println(toString()+" [CHILD] before"); } - if (nodeTest.type == XPath.NodeTest.QNAME) { - if (!nodeTest.name.equals(element)) { - if(fCurrentStep[i] > descendantStep) { - fCurrentStep[i] = descendantStep; - continue; - } - fNoMatchDepth[i]++; - if (DEBUG_MATCH) { - System.out.println(toString()+" [CHILD] after NO MATCH"); - } + if (!matches(nodeTest, element)) { + if (fCurrentStep[i] > descendantStep) { + fCurrentStep[i] = descendantStep; continue; } + fNoMatchDepth[i]++; + if (DEBUG_MATCH) { + System.out.println(toString()+" [CHILD] after NO MATCH"); + } + continue; } fCurrentStep[i]++; if (DEBUG_MATCH) { @@ -303,10 +302,11 @@ } } if (fCurrentStep[i] == steps.length) { - if(sawDescendant) { + if (sawDescendant) { fCurrentStep[i] = descendantStep; fMatched[i] = MATCHED_DESCENDANT; - } else { + } + else { fMatched[i] = MATCHED; } continue; @@ -324,8 +324,7 @@ for (int aIndex = 0; aIndex < attrCount; aIndex++) { attributes.getName(aIndex, fQName); - if (nodeTest.type != XPath.NodeTest.QNAME || - nodeTest.name.equals(fQName)) { + if (matches(nodeTest, fQName)) { fCurrentStep[i]++; if (fCurrentStep[i] == steps.length) { fMatched[i] = MATCHED_ATTRIBUTE; @@ -384,7 +383,7 @@ "element={"+element+"},"+ ")"); } - for(int i = 0; i<fLocationPaths.length; i++) { + for (int i = 0; i < fLocationPaths.length; i++) { // go back a step fCurrentStep[i] = fStepIndexes[i].pop(); @@ -395,10 +394,13 @@ // signal match, if appropriate else { - int j=0; - for(; j<i && ((fMatched[j] & MATCHED) != MATCHED); j++); - if ((j<i) || (fMatched[j] == 0) || - ((fMatched[j] & MATCHED_ATTRIBUTE) == MATCHED_ATTRIBUTE)) { + int j = 0; + for(; j < i && ((fMatched[j] & MATCHED) != MATCHED); j++); + if ((j < i) || (fMatched[j] == 0)) { + continue; + } + if ((fMatched[j] & MATCHED_ATTRIBUTE) == MATCHED_ATTRIBUTE) { + fMatched[i] = 0; continue; } // only certain kinds of matchers actually @@ -476,6 +478,18 @@ return str.toString(); } // normalize(String):String + /** Returns true if the given QName matches the node test. **/ + private static boolean matches(XPath.NodeTest nodeTest, QName value) { + if (nodeTest.type == XPath.NodeTest.QNAME) { + return nodeTest.name.equals(value); + } + if (nodeTest.type == XPath.NodeTest.NAMESPACE) { + return nodeTest.name.uri == value.uri; + } + // XPath.NodeTest.WILDCARD + return true; + } // matches(XPath.NodeTest,QName):boolean + // // MAIN //
--- a/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java Tue Jul 16 17:50:54 2019 +0200 +++ b/test/jaxp/javax/xml/jaxp/unittest/validation/ValidationTest.java Tue Jul 16 21:12:14 2019 +0000 @@ -36,11 +36,12 @@ import org.testng.annotations.Listeners; import org.testng.annotations.Test; +import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /* * @test - * @bug 8220818 + * @bug 8220818 8176447 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest * @run testng/othervm validation.ValidationTest * @summary Runs validations with schemas and sources @@ -71,6 +72,17 @@ }; } + /* + DataProvider: uniqueness + */ + @DataProvider(name = "uniqueness") + Object[][] getUniqueData() { + return new Object[][]{ + {"JDK8176447a.xsd", "JDK8176447a.xml"}, + {"JDK8176447b.xsd", "JDK8176447b.xml"}, + }; + } + @Test(dataProvider = "invalid", expectedExceptions = SAXParseException.class) public void testValidateRefType(String xsd, String xml) throws Exception { validate(xsd, xml); @@ -81,6 +93,19 @@ validate(xsd, xml); } + /** + * @bug 8176447 + * Verifies that the uniqueness constraint is checked. + * @param xsd the XSD + * @param xml the XML + * @throws Exception expected when the uniqueness constraint is validated + * correctly. + */ + @Test(dataProvider = "uniqueness", expectedExceptions = SAXException.class) + public void testUnique(String xsd, String xml) throws Exception { + validate(xsd, xml); + } + private void validate(String xsd, String xml) throws Exception { final SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI); @@ -90,4 +115,5 @@ validator.validate(new StreamSource( new File(getClass().getResource(FILE_PATH + xml).getFile()))); } + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447a.xml Tue Jul 16 21:12:14 2019 +0000 @@ -0,0 +1,8 @@ +<test xmlns="http://openjdk_java_net/test.xml" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="JDK8176447a.xsd"> + <innerObject> + <innerInnerObject test-unique-attribute="1" /> + <innerInnerObject test-unique-attribute="1" /> + </innerObject> +</test>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447a.xsd Tue Jul 16 21:12:14 2019 +0000 @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:h="http://www.w3.org/1999/xhtml" + xmlns:sn="http://openjdk_java_net/test.xml" + targetNamespace="http://openjdk_java_net/test.xml" elementFormDefault="qualified"> + <xsd:element name="test" type="sn:object"> + <xsd:unique name="testunique"> + <xsd:selector xpath="sn:innerObject"/> + <xsd:field xpath="sn:innerInnerObject/@test-unique-attribute"/> + </xsd:unique> + </xsd:element> + <xsd:complexType name="object"> + <xsd:sequence> + <xsd:element name="innerObject" maxOccurs="unbounded" type="sn:testType" /> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="testType"> + <xsd:sequence> + <xsd:element name="innerInnerObject" maxOccurs="unbounded" type="sn:testObjectType"/> + </xsd:sequence> + </xsd:complexType> + <xsd:complexType name="testObjectType"> + <xsd:attribute use="optional" name="test-unique-attribute" type="xsd:int" /> + </xsd:complexType> +</xsd:schema>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447b.xml Tue Jul 16 21:12:14 2019 +0000 @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="JDK8176447b.xsd"> + <e> + <e1 a1="a" > + <e2 a2="a"/> + <e2 a2="a"/> + </e1> + <e1 a1="a"> + <e2 a2="b"/> + <e2 a2="a"/> + </e1> + </e> +</root>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jaxp/javax/xml/jaxp/unittest/validation/files/JDK8176447b.xsd Tue Jul 16 21:12:14 2019 +0000 @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"> + <xs:element name="root"> + <xs:complexType> + <xs:sequence> + <xs:element name="e" maxOccurs="unbounded"> + <xs:complexType> + <xs:sequence> + <xs:element maxOccurs="unbounded" name="e1"> + <xs:complexType> + <xs:sequence> + <xs:element maxOccurs="unbounded" name="e2"> + <xs:complexType> + <xs:attribute name="a2" use="required" type="xs:NCName"/> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute name="a1" use="required" type="xs:NCName"/> + </xs:complexType> + </xs:element> + </xs:sequence> + </xs:complexType> + + <xs:key name="checkAttrib"> + <xs:selector xpath=".//e1"/> + <xs:field xpath="@a1"/> + <xs:field xpath="e2/@a2"/> + </xs:key> + + </xs:element> + </xs:sequence> + </xs:complexType> + </xs:element> +</xs:schema>