src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java
changeset 47359 e1a6c0168741
parent 47312 d4f959806fe9
child 47712 bde0215f1f70
equal deleted inserted replaced
47358:d07d5f7cab35 47359:e1a6c0168741
     1 /*
     1 /*
     2  * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
     3  * @LastModified: Sep 2017
     3  * @LastModified: Oct 2017
     4  */
     4  */
     5 /*
     5 /*
     6  * Licensed to the Apache Software Foundation (ASF) under one or more
     6  * Licensed to the Apache Software Foundation (ASF) under one or more
     7  * contributor license agreements.  See the NOTICE file distributed with
     7  * contributor license agreements.  See the NOTICE file distributed with
     8  * this work for additional information regarding copyright ownership.
     8  * this work for additional information regarding copyright ownership.
    81 import java.io.IOException;
    81 import java.io.IOException;
    82 import java.util.ArrayList;
    82 import java.util.ArrayList;
    83 import java.util.Collections;
    83 import java.util.Collections;
    84 import java.util.HashMap;
    84 import java.util.HashMap;
    85 import java.util.Iterator;
    85 import java.util.Iterator;
       
    86 import java.util.List;
    86 import java.util.Map;
    87 import java.util.Map;
    87 import java.util.Stack;
    88 import java.util.Stack;
    88 import java.util.Vector;
    89 import java.util.Vector;
    89 import javax.xml.XMLConstants;
    90 import javax.xml.XMLConstants;
    90 import jdk.xml.internal.JdkXmlUtils;
    91 import jdk.xml.internal.JdkXmlUtils;
   429         // the error reporter property
   430         // the error reporter property
   430         XMLErrorReporter fErrorReporter;
   431         XMLErrorReporter fErrorReporter;
   431 
   432 
   432         // store error codes; starting position of the errors for each element;
   433         // store error codes; starting position of the errors for each element;
   433         // number of element (depth); and whether to record error
   434         // number of element (depth); and whether to record error
   434         Vector fErrors = new Vector();
   435         Vector<String> fErrors = new Vector<>();
   435         int[] fContext = new int[INITIAL_STACK_SIZE];
   436         int[] fContext = new int[INITIAL_STACK_SIZE];
   436         int fContextCount;
   437         int fContextCount;
   437 
   438 
   438         // set the external error reporter, clear errors
   439         // set the external error reporter, clear errors
   439         public void reset(XMLErrorReporter errorReporter) {
   440         public void reset(XMLErrorReporter errorReporter) {
   472             if (size == 0)
   473             if (size == 0)
   473                 return null;
   474                 return null;
   474             // copy errors from the list to an string array
   475             // copy errors from the list to an string array
   475             String[] errors = new String[size];
   476             String[] errors = new String[size];
   476             for (int i = 0; i < size; i++) {
   477             for (int i = 0; i < size; i++) {
   477                 errors[i] = (String) fErrors.elementAt(contextPos + i);
   478                 errors[i] = fErrors.get(contextPos + i);
   478             }
   479             }
   479             // remove errors of the current element
   480             // remove errors of the current element
   480             fErrors.setSize(contextPos);
   481             fErrors.setSize(contextPos);
   481             return errors;
   482             return errors;
   482         }
   483         }
   496             if (size == 0)
   497             if (size == 0)
   497                 return null;
   498                 return null;
   498             // copy errors from the list to an string array
   499             // copy errors from the list to an string array
   499             String[] errors = new String[size];
   500             String[] errors = new String[size];
   500             for (int i = 0; i < size; i++) {
   501             for (int i = 0; i < size; i++) {
   501                 errors[i] = (String) fErrors.elementAt(contextPos + i);
   502                 errors[i] = fErrors.get(contextPos + i);
   502             }
   503             }
   503             // don't resize the vector: leave the errors for this attribute
   504             // don't resize the vector: leave the errors for this attribute
   504             // to the containing element
   505             // to the containing element
   505             return errors;
   506             return errors;
   506         }
   507         }
   507 
   508 
   508         public void reportError(String domain, String key, Object[] arguments, short severity)
   509         public void reportError(String domain, String key, Object[] arguments, short severity)
   509             throws XNIException {
   510             throws XNIException {
   510             String message = fErrorReporter.reportError(domain, key, arguments, severity);
   511             String message = fErrorReporter.reportError(domain, key, arguments, severity);
   511             if (fAugPSVI) {
   512             if (fAugPSVI) {
   512                 fErrors.addElement(key);
   513                 fErrors.add(key);
   513                 fErrors.addElement(message);
   514                 fErrors.add(message);
   514             }
   515             }
   515         } // reportError(String,String,Object[],short)
   516         } // reportError(String,String,Object[],short)
   516 
   517 
   517         public void reportError(
   518         public void reportError(
   518             XMLLocator location,
   519             XMLLocator location,
   521             Object[] arguments,
   522             Object[] arguments,
   522             short severity)
   523             short severity)
   523             throws XNIException {
   524             throws XNIException {
   524             String message = fErrorReporter.reportError(location, domain, key, arguments, severity);
   525             String message = fErrorReporter.reportError(location, domain, key, arguments, severity);
   525             if (fAugPSVI) {
   526             if (fAugPSVI) {
   526                 fErrors.addElement(key);
   527                 fErrors.add(key);
   527                 fErrors.addElement(message);
   528                 fErrors.add(message);
   528             }
   529             }
   529         } // reportError(XMLLocator,String,String,Object[],short)
   530         } // reportError(XMLLocator,String,String,Object[],short)
   530     }
   531     }
   531 
   532 
   532     /** Error reporter. */
   533     /** Error reporter. */
  1933             decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler);
  1934             decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler);
  1934             // it could be an element decl or a wildcard decl
  1935             // it could be an element decl or a wildcard decl
  1935             if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) {
  1936             if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) {
  1936                 XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
  1937                 XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
  1937                 //REVISIT: is it the only case we will have particle = null?
  1938                 //REVISIT: is it the only case we will have particle = null?
  1938                 ArrayList next;
  1939                 List<Object> next;
  1939                 if (ctype.fParticle != null
  1940                 if (ctype.fParticle != null
  1940                     && (next = fCurrentCM.whatCanGoHere(fCurrCMState)).size() > 0) {
  1941                     && (next = fCurrentCM.whatCanGoHere(fCurrCMState)).size() > 0) {
  1941                     String expected = expectedStr(next);
  1942                     String expected = expectedStr(next);
  1942                     final int[] occurenceInfo = fCurrentCM.occurenceInfo(fCurrCMState);
  1943                     final int[] occurenceInfo = fCurrentCM.occurenceInfo(fCurrCMState);
  1943                     String elemExpandedQname = (element.uri != null) ? "{"+'"'+element.uri+'"'+":"+element.localpart+"}" : element.localpart;
  1944                     String elemExpandedQname = (element.uri != null) ? "{"+'"'+element.uri+'"'+":"+element.localpart+"}" : element.localpart;
  2445 
  2446 
  2446         SchemaGrammar[] grammars = null;
  2447         SchemaGrammar[] grammars = null;
  2447         // have we reached the end tag of the validation root?
  2448         // have we reached the end tag of the validation root?
  2448         if (fElementDepth == 0) {
  2449         if (fElementDepth == 0) {
  2449             // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4).
  2450             // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4).
  2450             Iterator invIdRefs = fValidationState.checkIDRefID();
  2451             Iterator<String> invIdRefs = fValidationState.checkIDRefID();
  2451             fValidationState.resetIDTables();
  2452             fValidationState.resetIDTables();
  2452             if (invIdRefs != null) {
  2453             if (invIdRefs != null) {
  2453                 while (invIdRefs.hasNext()) {
  2454                 while (invIdRefs.hasNext()) {
  2454                     reportSchemaError("cvc-id.1", new Object[] { invIdRefs.next() });
  2455                     reportSchemaError("cvc-id.1", new Object[] { invIdRefs.next() });
  2455                 }
  2456                 }
  3507                 } else {
  3508                 } else {
  3508                     // Constant space algorithm for a{n,m} for n > 1 and m <= unbounded
  3509                     // Constant space algorithm for a{n,m} for n > 1 and m <= unbounded
  3509                     // After the DFA has completed, check minOccurs and maxOccurs
  3510                     // After the DFA has completed, check minOccurs and maxOccurs
  3510                     // for all elements and wildcards in this content model where
  3511                     // for all elements and wildcards in this content model where
  3511                     // a{n,m} is subsumed to a* or a+
  3512                     // a{n,m} is subsumed to a* or a+
  3512                     ArrayList errors = fCurrentCM.checkMinMaxBounds();
  3513                     List<String> errors = fCurrentCM.checkMinMaxBounds();
  3513                     if (errors != null) {
  3514                     if (errors != null) {
  3514                         for (int i = 0; i < errors.size(); i += 2) {
  3515                         for (int i = 0; i < errors.size(); i += 2) {
  3515                             reportSchemaError(
  3516                             reportSchemaError(errors.get(i),
  3516                                 (String) errors.get(i),
       
  3517                                 new Object[] { element.rawname, errors.get(i + 1) });
  3517                                 new Object[] { element.rawname, errors.get(i + 1) });
  3518                         }
  3518                         }
  3519                     }
  3519                     }
  3520                 }
  3520                 }
  3521             }
  3521             }
  3589                 key,
  3589                 key,
  3590                 arguments,
  3590                 arguments,
  3591                 XMLErrorReporter.SEVERITY_ERROR);
  3591                 XMLErrorReporter.SEVERITY_ERROR);
  3592     }
  3592     }
  3593 
  3593 
  3594     private String expectedStr(ArrayList expected) {
  3594     private String expectedStr(List<Object> expected) {
  3595         StringBuilder ret = new StringBuilder("{");
  3595         StringBuilder ret = new StringBuilder("{");
  3596         int size = expected.size();
  3596         int size = expected.size();
  3597         for (int i = 0; i < size; i++) {
  3597         for (int i = 0; i < size; i++) {
  3598             if (i > 0)
  3598             if (i > 0)
  3599                 ret.append(", ");
  3599                 ret.append(", ");
  3718 
  3718 
  3719         /** Current data value count. */
  3719         /** Current data value count. */
  3720         protected int fValuesCount;
  3720         protected int fValuesCount;
  3721 
  3721 
  3722         /** global data */
  3722         /** global data */
  3723         public final Vector fValues = new Vector();
  3723         public final Vector<Object> fValues = new Vector<>();
  3724         public ShortVector fValueTypes = null;
  3724         public ShortVector fValueTypes = null;
  3725         public Vector fItemValueTypes = null;
  3725         public Vector<ShortList> fItemValueTypes = null;
  3726 
  3726 
  3727         private boolean fUseValueTypeVector = false;
  3727         private boolean fUseValueTypeVector = false;
  3728         private int fValueTypesLength = 0;
  3728         private int fValueTypesLength = 0;
  3729         private short fValueType = 0;
  3729         private short fValueType = 0;
  3730 
  3730 
  3776         } // end clear():void
  3776         } // end clear():void
  3777 
  3777 
  3778         // appends the contents of one ValueStore to those of us.
  3778         // appends the contents of one ValueStore to those of us.
  3779         public void append(ValueStoreBase newVal) {
  3779         public void append(ValueStoreBase newVal) {
  3780             for (int i = 0; i < newVal.fValues.size(); i++) {
  3780             for (int i = 0; i < newVal.fValues.size(); i++) {
  3781                 fValues.addElement(newVal.fValues.elementAt(i));
  3781                 fValues.add(newVal.fValues.get(i));
  3782             }
  3782             }
  3783         } // append(ValueStoreBase)
  3783         } // append(ValueStoreBase)
  3784 
  3784 
  3785         /** Start scope for value store. */
  3785         /** Start scope for value store. */
  3786         public void startValueScope() {
  3786         public void startValueScope() {
  3891             fLocalItemValueTypes[i] = itemValueType;
  3891             fLocalItemValueTypes[i] = itemValueType;
  3892             if (fValuesCount == fFieldCount) {
  3892             if (fValuesCount == fFieldCount) {
  3893                 checkDuplicateValues();
  3893                 checkDuplicateValues();
  3894                 // store values
  3894                 // store values
  3895                 for (i = 0; i < fFieldCount; i++) {
  3895                 for (i = 0; i < fFieldCount; i++) {
  3896                     fValues.addElement(fLocalValues[i]);
  3896                     fValues.add(fLocalValues[i]);
  3897                     addValueType(fLocalValueTypes[i]);
  3897                     addValueType(fLocalValueTypes[i]);
  3898                     addItemValueType(fLocalItemValueTypes[i]);
  3898                     addItemValueType(fLocalItemValueTypes[i]);
  3899                 }
  3899                 }
  3900             }
  3900             }
  3901         } // addValue(String,Field)
  3901         } // addValue(String,Field)
  3910             final int size = fValues.size();
  3910             final int size = fValues.size();
  3911             LOOP : for (int i = 0; i < size; i = next) {
  3911             LOOP : for (int i = 0; i < size; i = next) {
  3912                 next = i + fFieldCount;
  3912                 next = i + fFieldCount;
  3913                 for (int j = 0; j < fFieldCount; j++) {
  3913                 for (int j = 0; j < fFieldCount; j++) {
  3914                     Object value1 = fLocalValues[j];
  3914                     Object value1 = fLocalValues[j];
  3915                     Object value2 = fValues.elementAt(i);
  3915                     Object value2 = fValues.get(i);
  3916                     short valueType1 = fLocalValueTypes[j];
  3916                     short valueType1 = fLocalValueTypes[j];
  3917                     short valueType2 = getValueTypeAt(i);
  3917                     short valueType2 = getValueTypeAt(i);
  3918                     if (value1 == null || value2 == null || valueType1 != valueType2 || !(value1.equals(value2))) {
  3918                     if (value1 == null || value2 == null || valueType1 != valueType2 || !(value1.equals(value2))) {
  3919                         continue LOOP;
  3919                         continue LOOP;
  3920                     }
  3920                     }
  3938          * values, otherwise the index of the first field in the
  3938          * values, otherwise the index of the first field in the
  3939          * key sequence.
  3939          * key sequence.
  3940          */
  3940          */
  3941         public int contains(ValueStoreBase vsb) {
  3941         public int contains(ValueStoreBase vsb) {
  3942 
  3942 
  3943             final Vector values = vsb.fValues;
  3943             final Vector<Object> values = vsb.fValues;
  3944             final int size1 = values.size();
  3944             final int size1 = values.size();
  3945             if (fFieldCount <= 1) {
  3945             if (fFieldCount <= 1) {
  3946                 for (int i = 0; i < size1; ++i) {
  3946                 for (int i = 0; i < size1; ++i) {
  3947                     short val = vsb.getValueTypeAt(i);
  3947                     short val = vsb.getValueTypeAt(i);
  3948                     if (!valueTypeContains(val) || !fValues.contains(values.elementAt(i))) {
  3948                     if (!valueTypeContains(val) || !fValues.contains(values.get(i))) {
  3949                         return i;
  3949                         return i;
  3950                     }
  3950                     }
  3951                     else if(val == XSConstants.LIST_DT || val == XSConstants.LISTOFUNION_DT) {
  3951                     else if(val == XSConstants.LIST_DT || val == XSConstants.LISTOFUNION_DT) {
  3952                         ShortList list1 = vsb.getItemValueTypeAt(i);
  3952                         ShortList list1 = vsb.getItemValueTypeAt(i);
  3953                         if (!itemValueTypeContains(list1)) {
  3953                         if (!itemValueTypeContains(list1)) {
  3962                 /** Iterate over each set of fields. **/
  3962                 /** Iterate over each set of fields. **/
  3963                 OUTER: for (int i = 0; i < size1; i += fFieldCount) {
  3963                 OUTER: for (int i = 0; i < size1; i += fFieldCount) {
  3964                     /** Check whether this set is contained in the value store. **/
  3964                     /** Check whether this set is contained in the value store. **/
  3965                     INNER: for (int j = 0; j < size2; j += fFieldCount) {
  3965                     INNER: for (int j = 0; j < size2; j += fFieldCount) {
  3966                         for (int k = 0; k < fFieldCount; ++k) {
  3966                         for (int k = 0; k < fFieldCount; ++k) {
  3967                             final Object value1 = values.elementAt(i+k);
  3967                             final Object value1 = values.get(i+k);
  3968                             final Object value2 = fValues.elementAt(j+k);
  3968                             final Object value2 = fValues.get(j+k);
  3969                             final short valueType1 = vsb.getValueTypeAt(i+k);
  3969                             final short valueType1 = vsb.getValueTypeAt(i+k);
  3970                             final short valueType2 = getValueTypeAt(j+k);
  3970                             final short valueType2 = getValueTypeAt(j+k);
  3971                             if (value1 != value2 && (valueType1 != valueType2 || value1 == null || !value1.equals(value2))) {
  3971                             if (value1 != value2 && (valueType1 != valueType2 || value1 == null || !value1.equals(value2))) {
  3972                                 continue INNER;
  3972                                 continue INNER;
  3973                             }
  3973                             }
  4017             return fTempBuffer.toString();
  4017             return fTempBuffer.toString();
  4018 
  4018 
  4019         } // toString(Object[]):String
  4019         } // toString(Object[]):String
  4020 
  4020 
  4021         /** Returns a string of the specified values. */
  4021         /** Returns a string of the specified values. */
  4022         protected String toString(Vector values, int start, int length) {
  4022         protected String toString(Vector<Object> values, int start, int length) {
  4023 
  4023 
  4024             // no values
  4024             // no values
  4025             if (length == 0) {
  4025             if (length == 0) {
  4026                 return "";
  4026                 return "";
  4027             }
  4027             }
  4028 
  4028 
  4029             // one value
  4029             // one value
  4030             if (length == 1) {
  4030             if (length == 1) {
  4031                 return String.valueOf(values.elementAt(start));
  4031                 return String.valueOf(values.get(start));
  4032             }
  4032             }
  4033 
  4033 
  4034             // construct value string
  4034             // construct value string
  4035             StringBuilder str = new StringBuilder();
  4035             StringBuilder str = new StringBuilder();
  4036             for (int i = 0; i < length; i++) {
  4036             for (int i = 0; i < length; i++) {
  4037                 if (i > 0) {
  4037                 if (i > 0) {
  4038                     str.append(',');
  4038                     str.append(',');
  4039                 }
  4039                 }
  4040                 str.append(values.elementAt(start + i));
  4040                 str.append(values.get(start + i));
  4041             }
  4041             }
  4042             return str.toString();
  4042             return str.toString();
  4043 
  4043 
  4044         } // toString(Vector,int,int):String
  4044         } // toString(Vector,int,int):String
  4045 
  4045 
  4107             }
  4107             }
  4108             else if (!(fItemValueType == itemValueType ||
  4108             else if (!(fItemValueType == itemValueType ||
  4109                     (fItemValueType != null && fItemValueType.equals(itemValueType)))) {
  4109                     (fItemValueType != null && fItemValueType.equals(itemValueType)))) {
  4110                 fUseItemValueTypeVector = true;
  4110                 fUseItemValueTypeVector = true;
  4111                 if (fItemValueTypes == null) {
  4111                 if (fItemValueTypes == null) {
  4112                     fItemValueTypes = new Vector(fItemValueTypesLength * 2);
  4112                     fItemValueTypes = new Vector<>(fItemValueTypesLength * 2);
  4113                 }
  4113                 }
  4114                 for (int i = 1; i < fItemValueTypesLength; ++i) {
  4114                 for (int i = 1; i < fItemValueTypesLength; ++i) {
  4115                     fItemValueTypes.add(fItemValueType);
  4115                     fItemValueTypes.add(fItemValueType);
  4116                 }
  4116                 }
  4117                 fItemValueTypes.add(itemValueType);
  4117                 fItemValueTypes.add(itemValueType);
  4118             }
  4118             }
  4119         }
  4119         }
  4120 
  4120 
  4121         private ShortList getItemValueTypeAt(int index) {
  4121         private ShortList getItemValueTypeAt(int index) {
  4122             if (fUseItemValueTypeVector) {
  4122             if (fUseItemValueTypeVector) {
  4123                 return (ShortList) fItemValueTypes.elementAt(index);
  4123                 return (ShortList) fItemValueTypes.get(index);
  4124             }
  4124             }
  4125             return fItemValueType;
  4125             return fItemValueType;
  4126         }
  4126         }
  4127 
  4127 
  4128         private boolean itemValueTypeContains(ShortList value) {
  4128         private boolean itemValueTypeContains(ShortList value) {
  4290         //
  4290         //
  4291         final LocalIDKey fLocalId = new LocalIDKey();
  4291         final LocalIDKey fLocalId = new LocalIDKey();
  4292         // values stores
  4292         // values stores
  4293 
  4293 
  4294         /** stores all global Values stores. */
  4294         /** stores all global Values stores. */
  4295         protected final ArrayList fValueStores = new ArrayList();
  4295         protected final List<ValueStoreBase> fValueStores = new ArrayList<>();
  4296 
  4296 
  4297         /**
  4297         /**
  4298          * Values stores associated to specific identity constraints.
  4298          * Values stores associated to specific identity constraints.
  4299          * This map maps IdentityConstraints and
  4299          * This map maps IdentityConstraints and
  4300          * the 0-based element on which their selectors first matched to
  4300          * the 0-based element on which their selectors first matched to
  4350             fGlobalMapStack.removeAllElements();
  4350             fGlobalMapStack.removeAllElements();
  4351         } // startDocument()
  4351         } // startDocument()
  4352 
  4352 
  4353         // startElement:  pushes the current fGlobalIDConstraintMap
  4353         // startElement:  pushes the current fGlobalIDConstraintMap
  4354         // onto fGlobalMapStack and clears fGlobalIDConstraint map.
  4354         // onto fGlobalMapStack and clears fGlobalIDConstraint map.
       
  4355         @SuppressWarnings("unchecked")
  4355         public void startElement() {
  4356         public void startElement() {
  4356             // only clone the map when there are elements
  4357             // only clone the map when there are elements
  4357             if (fGlobalIDConstraintMap.size() > 0)
  4358             if (fGlobalIDConstraintMap.size() > 0)
  4358                 fGlobalMapStack.push((Map<IdentityConstraint, ValueStoreBase>)
  4359                 fGlobalMapStack.push((Map<IdentityConstraint, ValueStoreBase>)
  4359                         ((HashMap)fGlobalIDConstraintMap).clone());
  4360                         ((HashMap<IdentityConstraint, ValueStoreBase>)fGlobalIDConstraintMap).clone());
  4360             else
  4361             else
  4361                 fGlobalMapStack.push(null);
  4362                 fGlobalMapStack.push(null);
  4362             fGlobalIDConstraintMap.clear();
  4363             fGlobalIDConstraintMap.clear();
  4363         } // startElement(void)
  4364         } // startElement(void)
  4364 
  4365 
  4481         } // transplant(id)
  4482         } // transplant(id)
  4482 
  4483 
  4483         /** Check identity constraints. */
  4484         /** Check identity constraints. */
  4484         public void endDocument() {
  4485         public void endDocument() {
  4485 
  4486 
  4486             int count = fValueStores.size();
  4487             for (ValueStoreBase valueStore : fValueStores) {
  4487             for (int i = 0; i < count; i++) {
       
  4488                 ValueStoreBase valueStore = (ValueStoreBase) fValueStores.get(i);
       
  4489                 valueStore.endDocument();
  4488                 valueStore.endDocument();
  4490             }
  4489             }
  4491 
  4490 
  4492         } // endDocument()
  4491         } // endDocument()
  4493 
  4492