8222991: Xerces 2.12.0: Validation
authorjoehw
Thu, 09 May 2019 09:23:31 -0700
changeset 54792 81607d4919c0
parent 54791 04f603ebb6c2
child 54794 019b3db480f4
8222991: Xerces 2.12.0: Validation Reviewed-by: lancea
src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/xs/TypeValidator.java
src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties
src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java
src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDComplexTypeTraverser.java
src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java
src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDSimpleTypeTraverser.java
test/jaxp/javax/xml/jaxp/unittest/validation/SchemaTest.java
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/xs/TypeValidator.java	Thu May 09 17:28:27 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/xs/TypeValidator.java	Thu May 09 09:23:31 2019 -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';
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties	Thu May 09 17:28:27 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties	Thu May 09 09:23:31 2019 -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 <complexContent> 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 <simpleContent> 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 <simpleType> among the children of <restriction>.
-        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
 
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java	Thu May 09 17:28:27 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDAbstractTraverser.java	Thu May 09 09:23:31 2019 -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<NamespaceContext> 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<String> 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<String> 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<String> 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
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDComplexTypeTraverser.java	Thu May 09 17:28:27 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDComplexTypeTraverser.java	Thu May 09 09:23:31 2019 -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 @@
  * </complexType>
  *
  * @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() {
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java	Thu May 09 17:28:27 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java	Thu May 09 09:23:31 2019 -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) {
+            if (is instanceof XSInputSource) {
+                // 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
-            if (is instanceof XSInputSource) {
-                return fGrammarBucket.getGrammar(desc.getTargetNamespace());
-            }
             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<SchemaGrammar> igs1 = (ArrayList<SchemaGrammar>)srcGrammar.getImportedGrammars();
-        if (igs1 != null) {
-           ArrayList<SchemaGrammar> igs2 = (ArrayList<SchemaGrammar>)dstGrammar.getImportedGrammars();
-
-            if (igs2 == null) {
-                igs2 = (ArrayList<SchemaGrammar>)igs1.clone();
-                dstGrammar.setImportedGrammars(igs2);
+        final ArrayList<SchemaGrammar> src = (ArrayList<SchemaGrammar>)srcGrammar.getImportedGrammars();
+        if (src != null) {
+            ArrayList<SchemaGrammar> dst = (ArrayList<SchemaGrammar>)dstGrammar.getImportedGrammars();
+            if (dst == null) {
+                dst = new ArrayList<>();
+                dstGrammar.setImportedGrammars(dst);
             }
-            else {
-                updateImportList(igs1, igs2);
+            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<XSObject> componentList, String namespace, Map<String, List<String>> 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<String> importedNamespaces = findDependentNamespaces(namespace, dependencies);
                     addNamespaceDependency(namespace, type.getNamespace(), importedNamespaces);
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDSimpleTypeTraverser.java	Thu May 09 17:28:27 2019 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDSimpleTypeTraverser.java	Thu May 09 09:23:31 2019 -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 {
--- a/test/jaxp/javax/xml/jaxp/unittest/validation/SchemaTest.java	Thu May 09 17:28:27 2019 +0200
+++ b/test/jaxp/javax/xml/jaxp/unittest/validation/SchemaTest.java	Thu May 09 09:23:31 2019 -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 = "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n" +
+                "    <xsd:simpleType name=\"PaymentStatus\">\n" +
+                "        <xsd:restriction base=\"xsd:string\">\n" +
+                "            <xsd:maxLength value=\"15\"/>\n" +
+                "            <xsd:enumeration value=\"AWAIT_PAY_INFO\"/>\n" +
+                "            <xsd:enumeration value=\"AWAIT_AUTH\"/>\n" +
+                "            <xsd:enumeration value=\"REQUESTED_AUTH\"/>\n" +
+                "            <xsd:enumeration value=\"REQUESTED_CHARGE\"/>\n" +
+                "            <xsd:enumeration value=\"PAID\"/>\n" +
+                "        </xsd:restriction>\n" +
+                "    </xsd:simpleType> \n" +
+                "</xsd:schema>";
+        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        final List<SAXParseException> 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