--- old/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/xs/TypeValidator.java 2019-04-29 12:58:09.067001789 -0700 +++ new/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/xs/TypeValidator.java 2019-04-29 12:58:08.489948891 -0700 @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -23,6 +22,8 @@ import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext; +import com.sun.org.apache.xerces.internal.util.XMLChar; +import jdk.xml.internal.SecuritySupport; /** * All primitive types plus ID/IDREF/ENTITY/INTEGER are derived from this abstract @@ -35,9 +36,14 @@ * @author Neeraj Bajaj, Sun Microsystems, inc. * @author Sandy Gao, IBM * + * @LastModified: Apr 2019 */ public abstract class TypeValidator { + private static final boolean USE_CODE_POINT_COUNT_FOR_STRING_LENGTH = + Boolean.parseBoolean(SecuritySupport.getSystemProperty( + "com.sun.org.apache.xerces.internal.impl.dv.xs.useCodePointCountForStringLength", "false")); + // which facets are allowed for this type public abstract short getAllowedFacets(); @@ -82,7 +88,14 @@ // get the length of the value // the parameters are in compiled form (from getActualValue) public int getDataLength(Object value) { - return (value instanceof String) ? ((String)value).length() : -1; + if (value instanceof String) { + final String str = (String)value; + if (!USE_CODE_POINT_COUNT_FOR_STRING_LENGTH) { + return str.length(); + } + return getCodePointLength(str); + } + return -1; } // get the number of digits of the value @@ -97,6 +110,25 @@ return -1; } + // Returns the length of the string in Unicode code points. + private int getCodePointLength(String value) { + // Count the number of surrogate pairs, and subtract them from + // the total length. + final int len = value.length(); + int surrogatePairCount = 0; + for (int i = 0; i < len - 1; ++i) { + if (XMLChar.isHighSurrogate(value.charAt(i))) { + if (XMLChar.isLowSurrogate(value.charAt(++i))) { + ++surrogatePairCount; + } + else { + --i; + } + } + } + return len - surrogatePairCount; + } + // check whether the character is in the range 0x30 ~ 0x39 public static final boolean isDigit(char ch) { return ch >= '0' && ch <= '9'; --- old/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties 2019-04-29 12:58:10.310115744 -0700 +++ new/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties 2019-04-29 12:58:09.730062571 -0700 @@ -39,7 +39,6 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: The content of element ''{0}'' is not complete. One of ''{1}'' is expected. cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration can be found for element ''{0}''. cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Invalid content was found starting with element ''{0}''. No child element is expected at this point. - cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: Invalid content was found starting with element ''{0}''. No child element ''{1}'' is expected at this point. cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}'' can occur a maximum of ''{2}'' times in the current sequence. This limit was exceeded. At this point one of ''{1}'' is expected. cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}'' can occur a maximum of ''{1}'' times in the current sequence. This limit was exceeded. No child element is expected at this point. cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Invalid content was found starting with element ''{0}''. ''{1}'' is expected to occur a minimum of ''{2}'' times in the current sequence. One more instance is required to satisfy this constraint. @@ -103,7 +102,7 @@ src-ct.1 = src-ct.1: Complex Type Definition Representation Error for type ''{0}''. When is used, the base type must be a complexType. ''{1}'' is a simpleType. src-ct.2.1 = src-ct.2.1: Complex Type Definition Representation Error for type ''{0}''. When is used, the base type must be a complexType whose content type is simple, or, only if restriction is specified, a complex type with mixed content and emptiable particle, or, only if extension is specified, a simple type. ''{1}'' satisfies none of these conditions. src-ct.2.2 = src-ct.2.2: Complex Type Definition Representation Error for type ''{0}''. When a complexType with simpleContent restricts a complexType with mixed content and emptiable particle, then there must be a among the children of . - src-ct.4 = src-ct.4: Complex Type Definition Representation Error for type ''{0}''. The intersection of wildcards is not expressible. + src-ct.4 = src-ct.4: Complex Type Definition Representation Error for type ''{0}''. The intersection of wildcards is not expressible. src-ct.5 = src-ct.5: Complex Type Definition Representation Error for type ''{0}''. The union of wildcards is not expressible. src-element.1 = src-element.1: The properties ''default'' and ''fixed'' cannot both be present in element declaration ''{0}''. Use only one of them. src-element.2.1 = src-element.2.1: : One of 'ref' or 'name' must be present in a local element declaration. @@ -234,14 +233,14 @@ rcase-MapAndSum.2 = rcase-MapAndSum.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base group''s occurrence range, ({2},{3}). rcase-NameAndTypeOK.1 = rcase-NameAndTypeOK.1: Elements have names and target namespaces which are not the same: Element ''{0}'' in namespace ''{1}'' and element ''{2}'' in namespace ''{3}''. rcase-NameAndTypeOK.2 = rcase-NameAndTypeOK.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. The element declaration''s '{'nillable'}' is true, but the corresponding particle in the base type has an element declaration whose '{'nillable'}' is false. - rcase-NameAndTypeOK.3 = rcase-NameAndTypeOK.3: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}, of the corresponding particle in the base type. + rcase-NameAndTypeOK.3 = rcase-NameAndTypeOK.3: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type. rcase-NameAndTypeOK.4.a = rcase-NameAndTypeOK.4.a: Element ''{0}'' is not fixed, but the corresponding element in the base type is fixed with value ''{1}''. rcase-NameAndTypeOK.4.b = rcase-NameAndTypeOK.4.b: Element ''{0}'' is fixed with value ''{1}'', but the corresponding element in the base type is fixed with value ''{2}''. rcase-NameAndTypeOK.5 = rcase-NameAndTypeOK.5: Identity constraints for element ''{0}'' are not a subset of those in base. rcase-NameAndTypeOK.6 = rcase-NameAndTypeOK.6: The disallowed substitutions for element ''{0}'' are not a superset of those in the base. rcase-NameAndTypeOK.7 = rcase-NameAndTypeOK.7: The type of element ''{0}'', ''{1}'', is not derived from the type of the base element, ''{2}''. rcase-NSCompat.1 = rcase-NSCompat.1: Element ''{0}'' has a namespace ''{1}'' which is not allowed by the wildcard in the base. - rcase-NSCompat.2 = rcase-NSCompat.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}, of the corresponding particle in the base type. + rcase-NSCompat.2 = rcase-NSCompat.2: Error for the particle whose '{'term'}' is the element declaration ''{0}''. Its occurrence range, ({1},{2}), is not a valid restriction of the range, ({3},{4}), of the corresponding particle in the base type. rcase-NSRecurseCheckCardinality.1 = rcase-NSRecurseCheckCardinality.1: There is not a complete functional mapping between the particles. rcase-NSRecurseCheckCardinality.2 = rcase-NSRecurseCheckCardinality.2: Group''s occurrence range, ({0},{1}), is not a valid restriction of base wildcard''s range, ({2},{3}). rcase-NSSubset.1 = rcase-NSSubset.1: Wildcard is not a subset of corresponding wildcard in base. @@ -286,15 +285,15 @@ EmptyTargetNamespace = EmptyTargetNamespace: In schema document ''{0}'', the value of the ''targetNamespace'' attribute cannot be an empty string. FacetValueFromBase = FacetValueFromBase: In the declaration of type ''{0}'', value ''{1}'' of facet ''{2}'' must be from the value space of the base type, ''{3}''. FixedFacetValue = FixedFacetValue: In the definition of {3}, the value ''{1}'' for the facet ''{0}'' is invalid, because the value for ''{0}'' has been set to ''{2}'' in one of the ancestor types, and '{'fixed'}' = true. - InvalidRegex = InvalidRegex: Pattern value ''{0}'' is not a valid regular expression. The reported error was: ''{1}'' at column ''{2}''. - MaxOccurLimit = Current configuration of the parser doesn''t allow a maxOccurs attribute value to be set greater than the value {0}. + InvalidRegex = InvalidRegex: Pattern value ''{0}'' is not a valid regular expression. The reported error was: ''{1}''. + MaxOccurLimit = Current configuration of the parser doesn''t allow the expansion of a content model for a complex type to contain more than {0} nodes. PublicSystemOnNotation = PublicSystemOnNotation: At least one of ''public'' and ''system'' must appear in element ''notation''. SchemaLocation = SchemaLocation: schemaLocation value = ''{0}'' must have even number of URI''s. TargetNamespace.1 = TargetNamespace.1: Expecting namespace ''{0}'', but the target namespace of the schema document is ''{1}''. TargetNamespace.2 = TargetNamespace.2: Expecting no namespace, but the schema document has a target namespace of ''{1}''. UndeclaredEntity = UndeclaredEntity: Entity ''{0}'' is not declared. UndeclaredPrefix = UndeclaredPrefix: Cannot resolve ''{0}'' as a QName: the prefix ''{1}'' is not declared. - + FacetsContradict = FacetsContradict: For simpleType definition ''{2}'', the enumeration value ''{0}'' contradicts with value of ''{1}'' facet. # JAXP 1.2 schema source property errors --- old/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java 2019-04-29 12:58:11.505225299 -0700 +++ new/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java 2019-04-29 12:58:10.935173042 -0700 @@ -23,6 +23,8 @@ import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; import com.sun.org.apache.xerces.internal.impl.dv.XSFacets; import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; +import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; +import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl; import com.sun.org.apache.xerces.internal.impl.validation.ValidationState; import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar; import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols; @@ -42,6 +44,7 @@ import com.sun.org.apache.xerces.internal.xni.QName; import com.sun.org.apache.xerces.internal.xs.XSAttributeUse; import com.sun.org.apache.xerces.internal.xs.XSObjectList; +import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition; import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; import java.util.ArrayList; import java.util.List; @@ -280,6 +283,7 @@ } FacetInfo traverseFacets(Element content, + XSTypeDefinition typeDef, XSSimpleType baseValidator, XSDocumentInfo schemaDoc) { @@ -293,6 +297,9 @@ List enumNSDecls = hasQName ? new ArrayList<>() : null; int currentFacet = 0; xsFacets.reset(); + boolean seenPattern = false; + Element contextNode = (Element)content.getParentNode(); + boolean hasLengthFacet = false, hasMinLengthFacet = false, hasMaxLengthFacet = false; while (content != null) { // General Attribute Checking Object[] attrs = null; @@ -364,7 +371,6 @@ } } else if (facet.equals(SchemaSymbols.ELT_PATTERN)) { - facetsPresent |= XSSimpleType.FACET_PATTERN; attrs = fAttrChecker.checkAttributes(content, false, schemaDoc); String patternVal = (String)attrs[XSAttributeChecker.ATTIDX_VALUE]; // The facet can't be used if the value is missing. Ignore @@ -376,6 +382,7 @@ continue; } + seenPattern = true; if (fPattern.length() == 0) { fPattern.append(patternVal); } else { @@ -477,9 +484,11 @@ switch (currentFacet) { case XSSimpleType.FACET_MINLENGTH: xsFacets.minLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue(); + hasMinLengthFacet = true; break; case XSSimpleType.FACET_MAXLENGTH: xsFacets.maxLength = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue(); + hasMaxLengthFacet = true; break; case XSSimpleType.FACET_MAXEXCLUSIVE: xsFacets.maxExclusive = (String)attrs[XSAttributeChecker.ATTIDX_VALUE]; @@ -504,6 +513,7 @@ break; case XSSimpleType.FACET_LENGTH: xsFacets.length = ((XInt)attrs[XSAttributeChecker.ATTIDX_VALUE]).intValue(); + hasLengthFacet = true; break; } @@ -566,16 +576,148 @@ xsFacets.enumNSDecls = enumNSDecls; xsFacets.enumAnnotations = enumAnnotations; } - if ((facetsPresent & XSSimpleType.FACET_PATTERN) != 0) { + if (seenPattern) { + facetsPresent |= XSSimpleType.FACET_PATTERN; xsFacets.pattern = fPattern.toString(); xsFacets.patternAnnotations = patternAnnotations; } fPattern.setLength(0); + // check if length, minLength and maxLength facets contradict with enumeration facets. + // currently considers the case when the baseValidator is a built-in type. + if (enumData != null) { + if (hasLengthFacet) { + checkEnumerationAndLengthInconsistency(baseValidator, enumData, contextNode, getSchemaTypeName(typeDef)); + } + if (hasMinLengthFacet) { + checkEnumerationAndMinLengthInconsistency(baseValidator, enumData, contextNode, getSchemaTypeName(typeDef)); + } + if (hasMaxLengthFacet) { + checkEnumerationAndMaxLengthInconsistency(baseValidator, enumData, contextNode, getSchemaTypeName(typeDef)); + } + } + return new FacetInfo(xsFacets, content, facetsPresent, facetsFixed); } + /* + * Get name of an XSD type definition as a string value (which will typically be the value of "name" attribute of a + * type definition, or an internal name determined by the validator for anonymous types). + */ + public static String getSchemaTypeName(XSTypeDefinition typeDefn) { + + String typeNameStr = ""; + if (typeDefn instanceof XSSimpleTypeDefinition) { + typeNameStr = ((XSSimpleTypeDecl) typeDefn).getTypeName(); + } + else { + typeNameStr = ((XSComplexTypeDecl) typeDefn).getTypeName(); + } + + return typeNameStr; + + } // getSchemaTypeName + + /* + * Check whether values of xs:maxLength and xs:enumeration are consistent. Report a warning message if they are not. + */ + private void checkEnumerationAndMaxLengthInconsistency(XSSimpleType baseValidator, List enumData, Element contextNode, String typeName) { + if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) && + SchemaSymbols.ATTVAL_HEXBINARY.equals(baseValidator.getName())) { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + if (enumVal.length() / 2 > xsFacets.maxLength) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MAXLENGTH, typeName}, contextNode); + } + } + } + else if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) && + SchemaSymbols.ATTVAL_BASE64BINARY.equals(baseValidator.getName())) { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + byte[] decodedVal = Base64.decode(enumVal); + if (decodedVal != null && (new String(decodedVal)).length() > xsFacets.maxLength) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MAXLENGTH, typeName}, contextNode); + } + } + } + else { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + if (enumVal.length() > xsFacets.maxLength) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MAXLENGTH, typeName}, contextNode); + } + } + } + } // checkEnumerationAndMaxLengthInconsistency + + /* + * Check whether values of xs:minLength and xs:enumeration are consistent. Report a warning message if they are not. + */ + private void checkEnumerationAndMinLengthInconsistency(XSSimpleType baseValidator, List enumData, Element contextNode, String typeName) { + if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) && + SchemaSymbols.ATTVAL_HEXBINARY.equals(baseValidator.getName())) { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + if (enumVal.length() / 2 < xsFacets.minLength) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MINLENGTH, typeName}, contextNode); + } + } + } + else if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) && + SchemaSymbols.ATTVAL_BASE64BINARY.equals(baseValidator.getName())) { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + byte[] decodedVal = Base64.decode(enumVal); + if (decodedVal != null && (new String(decodedVal)).length() < xsFacets.minLength) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MINLENGTH, typeName}, contextNode); + } + } + } + else { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + if (enumVal.length() < xsFacets.minLength) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_MINLENGTH, typeName}, contextNode); + } + } + } + } // checkEnumerationAndMinLengthInconsistency + + /* + * Check whether values of xs:length and xs:enumeration are consistent. Report a warning message if they are not. + */ + private void checkEnumerationAndLengthInconsistency(XSSimpleType baseValidator, List enumData, Element contextNode, String typeName) { + if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) && + SchemaSymbols.ATTVAL_HEXBINARY.equals(baseValidator.getName())) { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + if (enumVal.length() / 2 != xsFacets.length) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_LENGTH, typeName}, contextNode); + } + } + } + else if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(baseValidator.getNamespace()) && + SchemaSymbols.ATTVAL_BASE64BINARY.equals(baseValidator.getName())) { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + byte[] decodedVal = Base64.decode(enumVal); + if (decodedVal != null && (new String(decodedVal)).length() != xsFacets.length) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_LENGTH, typeName}, contextNode); + } + } + } + else { + for (int enumIdx = 0; enumIdx < enumData.size(); enumIdx++) { + String enumVal = (enumData.get(enumIdx)); + if (enumVal.length() != xsFacets.length) { + reportSchemaWarning("FacetsContradict", new Object[]{enumVal, SchemaSymbols.ELT_LENGTH, typeName}, contextNode); + } + } + } + } // checkEnumerationAndLengthInconsistency + // return whether QName/NOTATION is part of the given type private boolean containsQName(XSSimpleType type) { @@ -724,6 +866,10 @@ fSchemaHandler.reportSchemaError(key, args, ele); } + void reportSchemaWarning (String key, Object[] args, Element ele) { + fSchemaHandler.reportSchemaWarning(key, args, ele); + } + /** * Element/Attribute traversers call this method to check whether * the type is NOTATION without enumeration facet --- old/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDComplexTypeTraverser.java 2019-04-29 12:58:12.733337879 -0700 +++ new/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDComplexTypeTraverser.java 2019-04-29 12:58:12.157285072 -0700 @@ -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 @@ -62,7 +62,7 @@ * * * @xerces.internal - * + * @LastModified: Apr 2019 */ class XSDComplexTypeTraverser extends XSDAbstractParticleTraverser { @@ -574,7 +574,7 @@ short fixedFacets = 0 ; if (simpleContent!=null) { - FacetInfo fi = traverseFacets(simpleContent, baseValidator, schemaDoc); + FacetInfo fi = traverseFacets(simpleContent, fComplexTypeDecl, baseValidator, schemaDoc); attrNode = fi.nodeAfterFacets; facetData = fi.facetdata; presentFacets = fi.fPresentFacets; @@ -1193,9 +1193,6 @@ // REVISIT: do we need to remove all attribute uses already added into // the attribute group? maybe it's ok to leave them there. -SG fAttrGrp.fAttributeWC = getErrorWildcard(); - - return; - } private void contentBackup() { --- old/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java 2019-04-29 12:58:13.950449450 -0700 +++ new/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java 2019-04-29 12:58:13.380397194 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -60,6 +60,7 @@ import com.sun.org.apache.xerces.internal.util.SymbolHash; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException; +import com.sun.org.apache.xerces.internal.util.XMLChar; import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; @@ -129,7 +130,7 @@ * @author Neil Graham, IBM * @author Pavani Mukthipudi, Sun Microsystems * - * @LastModified: Nov 2017 + * @LastModified: Apr 2019 */ @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory public class XSDHandler { @@ -591,10 +592,27 @@ } //is instanceof XMLInputSource if (schemaRoot == null) { - // something went wrong right off the hop if (is instanceof XSInputSource) { - return fGrammarBucket.getGrammar(desc.getTargetNamespace()); + // Need to return a grammar. If the XSInputSource has a list + // of grammar objects, then get the first one and return it. + // If it has a list of components, then get the grammar that + // contains the first component and return it. + // If we return null, the XMLSchemaLoader will think nothing + // was loaded, and will not try to put the grammar objects + // into the grammar pool. + XSInputSource xsinput = (XSInputSource)is; + SchemaGrammar[] grammars = xsinput.getGrammars(); + if (grammars != null && grammars.length > 0) { + grammar = fGrammarBucket.getGrammar(grammars[0].getTargetNamespace()); + } + else { + XSObject[] components = xsinput.getComponents(); + if (components != null && components.length > 0) { + grammar = fGrammarBucket.getGrammar(components[0].getNamespace()); + } + } } + // something went wrong right off the hop return grammar; } @@ -1299,6 +1317,7 @@ String qName = currSchemaDoc.fTargetNamespace == null ? ","+lName: currSchemaDoc.fTargetNamespace +","+lName; + qName = XMLChar.trim(qName); String componentType = DOMUtil.getLocalName(redefineComp); if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) { checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, redefineComp, currSchemaDoc); @@ -1343,6 +1362,7 @@ String qName = currSchemaDoc.fTargetNamespace == null? ","+lName: currSchemaDoc.fTargetNamespace +","+lName; + qName = XMLChar.trim(qName); String componentType = DOMUtil.getLocalName(globalComp); if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) { @@ -2466,9 +2486,15 @@ return getSchemaDocument0(key, schemaId, schemaElement); } catch (XMLStreamException e) { - StAXLocationWrapper slw = new StAXLocationWrapper(); - slw.setLocation(e.getLocation()); - throw new XMLParseException(slw, e.getMessage(), e); + Throwable t = e.getNestedException(); + if (t instanceof IOException) { + exception = (IOException) t; + } + else { + StAXLocationWrapper slw = new StAXLocationWrapper(); + slw.setLocation(e.getLocation()); + throw new XMLParseException(slw, e.getMessage(), e); + } } catch (IOException e) { exception = e; @@ -2741,16 +2767,29 @@ @SuppressWarnings("unchecked") private void addNewImportedGrammars(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) { - final ArrayList igs1 = (ArrayList)srcGrammar.getImportedGrammars(); - if (igs1 != null) { - ArrayList igs2 = (ArrayList)dstGrammar.getImportedGrammars(); - - if (igs2 == null) { - igs2 = (ArrayList)igs1.clone(); - dstGrammar.setImportedGrammars(igs2); - } - else { - updateImportList(igs1, igs2); + final ArrayList src = (ArrayList)srcGrammar.getImportedGrammars(); + if (src != null) { + ArrayList dst = (ArrayList)dstGrammar.getImportedGrammars(); + if (dst == null) { + dst = new ArrayList<>(); + dstGrammar.setImportedGrammars(dst); + } + for (SchemaGrammar sg :src) { + // Can't use the object from the source import list directly. + // It's possible there is already a grammar with the same + // namespace in the bucket but a different object. + // This can happen if the bucket has grammar A1, and we try + // to add B and A2, where A2 imports B. When B is added, we + // create a new object B' and store it in the bucket. Then we + // try to merge A2 and A1. We can't use B. Need to get B' from + // the bucket and store it in A's import list. + SchemaGrammar sg1 = fGrammarBucket.getGrammar(sg.getTargetNamespace()); + if (sg1 != null) { + sg = sg1; + } + if (!containedImportedGrammar(dst, sg)) { + dst.add(sg); + } } } } @@ -3162,7 +3201,7 @@ private void addRelatedType(XSTypeDefinition type, List componentList, String namespace, Map> dependencies) { if (!type.getAnonymous()) { - if (!type.getNamespace().equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) { //REVISIT - do we use == instead + if (!SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(type.getNamespace())) { //REVISIT - do we use == instead if (!componentList.contains(type)) { final List importedNamespaces = findDependentNamespaces(namespace, dependencies); addNamespaceDependency(namespace, type.getNamespace(), importedNamespaces); --- old/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDSimpleTypeTraverser.java 2019-04-29 12:58:15.204564414 -0700 +++ new/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDSimpleTypeTraverser.java 2019-04-29 12:58:14.638512524 -0700 @@ -395,7 +395,7 @@ } // now traverse facets, if it's derived by restriction if (restriction && content != null) { - FacetInfo fi = traverseFacets(content, baseValidator, schemaDoc); + FacetInfo fi = traverseFacets(content, newDecl, baseValidator, schemaDoc); content = fi.nodeAfterFacets; try { --- old/test/jaxp/javax/xml/jaxp/unittest/validation/SchemaTest.java 2019-04-29 12:58:16.415675435 -0700 +++ new/test/jaxp/javax/xml/jaxp/unittest/validation/SchemaTest.java 2019-04-29 12:58:15.844623087 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, 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 @@ -24,23 +24,70 @@ package validation; import java.io.File; - +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; import javax.xml.XMLConstants; +import javax.xml.transform.stream.StreamSource; import javax.xml.validation.SchemaFactory; - +import org.testng.Assert; import org.testng.annotations.Listeners; import org.testng.annotations.Test; +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; /* * @test + * @bug 8149915 8222991 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest - * @run testng/othervm -DrunSecMngr=true validation.SchemaTest * @run testng/othervm validation.SchemaTest * @summary Test Schema creation - * @bug 8149915 */ @Listeners({jaxp.library.FilePolicy.class}) public class SchemaTest { + /** + * Verifies that an over-the-limit value of an enumeration is caught as a + * warning. + * @throws Exception if the test fails + */ + @Test + public void testSchema() throws Exception { + String xsd = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + final List exceptions = new ArrayList<>(); + + factory.setErrorHandler(new ErrorHandler() + { + @Override + public void warning(SAXParseException exception) throws SAXException + { + exceptions.add(exception); + } + + @Override + public void fatalError(SAXParseException exception) throws SAXException + {} + + @Override + public void error(SAXParseException exception) throws SAXException + {} + }); + factory.newSchema(new StreamSource(new StringReader(xsd))); + Assert.assertTrue(exceptions.get(0).toString().contains("FacetsContradict"), + "Report warning when the maxLength limit is exceeded in an enumeration"); + } /* * @bug 8149915