| 1 57 58 package org.enhydra.apache.xerces.validators.common; 59 60 import java.io.IOException ; 61 import java.util.Enumeration ; 62 import java.util.Hashtable ; 63 import java.util.Stack ; 64 import java.util.StringTokenizer ; 65 import java.util.Vector ; 66 67 import org.enhydra.apache.xerces.framework.XMLAttrList; 68 import org.enhydra.apache.xerces.framework.XMLContentSpec; 69 import org.enhydra.apache.xerces.framework.XMLDocumentHandler; 70 import org.enhydra.apache.xerces.framework.XMLDocumentScanner; 71 import org.enhydra.apache.xerces.framework.XMLErrorReporter; 72 import org.enhydra.apache.xerces.parsers.DOMParser; 73 import org.enhydra.apache.xerces.readers.DefaultEntityHandler; 74 import org.enhydra.apache.xerces.readers.XMLEntityHandler; 75 import org.enhydra.apache.xerces.utils.ImplementationMessages; 76 import org.enhydra.apache.xerces.utils.IntStack; 77 import org.enhydra.apache.xerces.utils.NamespacesScope; 78 import org.enhydra.apache.xerces.utils.QName; 79 import org.enhydra.apache.xerces.utils.StringPool; 80 import org.enhydra.apache.xerces.utils.XMLMessages; 81 import org.enhydra.apache.xerces.validators.datatype.AnySimpleType; 82 import org.enhydra.apache.xerces.validators.datatype.DatatypeValidator; 83 import org.enhydra.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl; 84 import org.enhydra.apache.xerces.validators.datatype.ENTITYDatatypeValidator; 85 import org.enhydra.apache.xerces.validators.datatype.IDDatatypeValidator; 86 import org.enhydra.apache.xerces.validators.datatype.IDREFDatatypeValidator; 87 import org.enhydra.apache.xerces.validators.datatype.InvalidDatatypeValueException; 88 import org.enhydra.apache.xerces.validators.datatype.NOTATIONDatatypeValidator; 89 import org.enhydra.apache.xerces.validators.datatype.StateMessageDatatype; 90 import org.enhydra.apache.xerces.validators.datatype.UnionDatatypeValidator; 91 import org.enhydra.apache.xerces.validators.dtd.DTDGrammar; 92 import org.enhydra.apache.xerces.validators.schema.GeneralAttrCheck; 93 import org.enhydra.apache.xerces.validators.schema.SchemaGrammar; 94 import org.enhydra.apache.xerces.validators.schema.SchemaMessageProvider; 95 import org.enhydra.apache.xerces.validators.schema.SchemaSymbols; 96 import org.enhydra.apache.xerces.validators.schema.SubstitutionGroupComparator; 97 import org.enhydra.apache.xerces.validators.schema.TraverseSchema; 98 import org.enhydra.apache.xerces.validators.schema.identity.Field; 99 import org.enhydra.apache.xerces.validators.schema.identity.FieldActivator; 100 import org.enhydra.apache.xerces.validators.schema.identity.IDValue; 101 import org.enhydra.apache.xerces.validators.schema.identity.IdentityConstraint; 102 import org.enhydra.apache.xerces.validators.schema.identity.Key; 103 import org.enhydra.apache.xerces.validators.schema.identity.KeyRef; 104 import org.enhydra.apache.xerces.validators.schema.identity.Selector; 105 import org.enhydra.apache.xerces.validators.schema.identity.Unique; 106 import org.enhydra.apache.xerces.validators.schema.identity.ValueStore; 107 import org.enhydra.apache.xerces.validators.schema.identity.XPathMatcher; 108 import org.w3c.dom.Document ; 109 import org.w3c.dom.Element ; 110 import org.xml.sax.EntityResolver ; 111 import org.xml.sax.InputSource ; 112 import org.xml.sax.Locator ; 113 import org.xml.sax.SAXException ; 114 import org.xml.sax.SAXParseException ; 115 import org.xml.sax.helpers.LocatorImpl ; 116 117 122 public final class XMLValidator 123 implements DefaultEntityHandler.EventHandler, 124 XMLEntityHandler.CharDataHandler, 125 XMLDocumentScanner.EventHandler, 126 NamespacesScope.NamespacesHandler, 127 FieldActivator { 129 130 134 136 private static final boolean PRINT_EXCEPTION_STACK_TRACE = false; 137 private static final boolean DEBUG_PRINT_ATTRIBUTES = false; 138 private static final boolean DEBUG_PRINT_CONTENT = false; 139 private static final boolean DEBUG_SCHEMA_VALIDATION = false; 140 private static final boolean DEBUG_ELEMENT_CHILDREN = false; 141 142 143 protected static final boolean DEBUG_IDENTITY_CONSTRAINTS = false; 144 145 146 protected static final boolean DEBUG_VALUE_STORES = false; 147 148 150 private static final int CHUNK_SHIFT = 8; private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT); 152 private static final int CHUNK_MASK = CHUNK_SIZE - 1; 153 private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT)); 155 private Hashtable fIdDefs = new Hashtable (); 156 private Hashtable fIdREFDefs = new Hashtable (); 157 158 private StateMessageDatatype fValidateIDRef = new StateMessageDatatype() { 159 private Hashtable fIdDefs; 160 public Object getDatatypeObject(){ 161 return(Object ) fIdDefs; 162 } 163 public int getDatatypeState(){ 164 return IDREFDatatypeValidator.IDREF_VALIDATE; 165 } 166 public void setDatatypeObject( Object data ){ 167 fIdDefs = (Hashtable ) data; 168 } 169 }; 170 171 private StateMessageDatatype fCheckIDRef = new StateMessageDatatype() { 172 private Object [] fLists; 173 public Object getDatatypeObject(){ 174 return(Object ) fLists; 175 } 176 public int getDatatypeState(){ 177 return IDREFDatatypeValidator.IDREF_CHECKID; 178 } 179 public void setDatatypeObject( Object data ){ 180 fLists = (Object []) data; 181 } 182 }; 183 184 private StateMessageDatatype fValidateEntity = new StateMessageDatatype() { 185 private Object fData; 186 public Object getDatatypeObject(){ 187 return fData; 188 } 189 public int getDatatypeState(){ 190 return ENTITYDatatypeValidator.ENTITY_VALIDATE; 191 } 192 public void setDatatypeObject( Object data ){ 193 fData = data; 194 } 195 }; 196 197 201 204 206 private AttributeValidator fAttValidatorNOTATION = new AttValidatorNOTATION(); 207 private AttributeValidator fAttValidatorENUMERATION = new AttValidatorENUMERATION(); 208 private AttributeValidator fAttValidatorDATATYPE = null; 209 210 212 StringPool fStringPool = null; 213 boolean fValidating = false; 214 boolean fInElementContent = false; 215 int fStandaloneReader = -1; 216 217 218 220 private boolean fValidationEnabled = false; 221 private boolean fDynamicValidation = false; 222 private boolean fSchemaValidation = true; 223 private boolean fSchemaValidationFullChecking = false; 224 private boolean fValidationEnabledByDynamic = false; 225 private boolean fDynamicDisabledByValidation = false; 226 private boolean fWarningOnDuplicateAttDef = false; 227 private boolean fWarningOnUndeclaredElements = false; 228 private boolean fNormalizeAttributeValues = true; 229 private boolean fLoadDTDGrammar = true; 230 private boolean fNormalizeContents = false; 233 234 239 241 private Hashtable fLocationUriPairs = new Hashtable (10); 242 243 244 246 private String fExternalSchemas = null; 247 private String fExternalNoNamespaceSchema = null; 248 private DOMParser fSchemaGrammarParser = null; 249 private int fDeclaration[]; 250 private XMLErrorReporter fErrorReporter = null; 251 private DefaultEntityHandler fEntityHandler = null; 252 private QName fCurrentElement = new QName(); 253 254 private ContentLeafNameTypeVector[] fContentLeafStack = new ContentLeafNameTypeVector[8]; 255 256 private XMLContentModel[] fContentModelStack = new XMLContentModel[8]; 259 private int[] fContentModelStateStack = new int[8]; 261 private int[] fContentModelEleCount = new int[8]; 263 264 private int[] fValidationFlagStack = new int[8]; 265 266 private int[] fScopeStack = new int[8]; 267 private int[] fGrammarNameSpaceIndexStack = new int[8]; 268 269 private int[] fElementEntityStack = new int[8]; 270 private int[] fElementIndexStack = new int[8]; 271 private int[] fContentSpecTypeStack = new int[8]; 272 273 private static final int sizeQNameParts = 8; 274 private QName[] fElementQNamePartsStack = new QName[sizeQNameParts]; 275 276 private QName[] fElementChildren = new QName[32]; 277 private int fElementChildrenLength = 0; 278 private int[] fElementChildrenOffsetStack = new int[32]; 279 private int fElementDepth = -1; 280 281 private boolean fNamespacesEnabled = false; 282 private NamespacesScope fNamespacesScope = null; 283 private int fNamespacesPrefix = -1; 284 private QName fRootElement = new QName(); 285 private int fAttrListHandle = -1; 286 private int fCurrentElementEntity = -1; 287 private int fCurrentElementIndex = -1; 288 private int fCurrentContentSpecType = -1; 289 private boolean fSeenDoctypeDecl = false; 290 291 private final int TOP_LEVEL_SCOPE = -1; 292 private int fCurrentScope = TOP_LEVEL_SCOPE; 293 private int fCurrentSchemaURI = StringPool.EMPTY_STRING; 294 private int fEmptyURI = StringPool.EMPTY_STRING; 295 private int fXsiPrefix = - 1; 296 private int fXsiURI = -2; 297 private int fXsiTypeAttValue = -1; 298 private DatatypeValidator fXsiTypeValidator = null; 299 300 private boolean fNil = false; 301 302 private Grammar fGrammar = null; 303 private int fGrammarNameSpaceIndex = StringPool.EMPTY_STRING; 304 private GrammarResolver fGrammarResolver = null; 305 306 307 309 private boolean fScanningDTD = false; 310 private XMLDocumentScanner fDocumentScanner = null; 311 private boolean fCalledStartDocument = false; 312 private XMLDocumentHandler fDocumentHandler = null; 313 private XMLDocumentHandler.DTDHandler fDTDHandler = null; 314 private boolean fSeenRootElement = false; 315 private XMLAttrList fAttrList = null; 316 private int fXMLLang = -1; 317 private LocatorImpl fAttrNameLocator = null; 318 private boolean fCheckedForSchema = false; 319 private boolean fDeclsAreExternal = false; 320 private StringPool.CharArrayRange fCurrentElementCharArrayRange = null; 321 private char[] fCharRefData = null; 322 private boolean fSendCharDataAsCharArray = false; 323 private boolean fBufferDatatype = false; 324 private StringBuffer fDatatypeBuffer = new StringBuffer (); 326 327 private QName fTempQName = new QName(); 328 private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl(); 329 private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl(); 330 private XMLElementDecl fTempElementDecl = new XMLElementDecl(); 331 332 private boolean fGrammarIsDTDGrammar = false; 333 private boolean fGrammarIsSchemaGrammar = false; 334 335 private boolean fNeedValidationOff = false; 336 337 private static final boolean DEBUG_NORMALIZATION = false; 339 private DatatypeValidator fCurrentDV = null; private boolean fFirstChunk = true; private boolean fTrailing = false; private short fWhiteSpace = DatatypeValidator.COLLAPSE; private StringBuffer fNormalizedStr = new StringBuffer (CHUNK_SIZE); private StringBuffer fUnnormalizedStr = new StringBuffer (CHUNK_SIZE); 346 347 348 350 private int fEMPTYSymbol = -1; 351 private int fANYSymbol = -1; 352 private int fMIXEDSymbol = -1; 353 private int fCHILDRENSymbol = -1; 354 private int fCDATASymbol = -1; 355 private int fIDSymbol = -1; 356 private int fIDREFSymbol = -1; 357 private int fIDREFSSymbol = -1; 358 private int fENTITYSymbol = -1; 359 private int fENTITIESSymbol = -1; 360 private int fNMTOKENSymbol = -1; 361 private int fNMTOKENSSymbol = -1; 362 private int fNOTATIONSymbol = -1; 363 private int fENUMERATIONSymbol = -1; 364 private int fREQUIREDSymbol = -1; 365 private int fFIXEDSymbol = -1; 366 private int fDATATYPESymbol = -1; 367 private int fEpsilonIndex = -1; 368 369 370 372 private DatatypeValidatorFactoryImpl fDataTypeReg = null; 373 private DatatypeValidator fValID = null; 374 private DatatypeValidator fValIDRef = null; 375 private DatatypeValidator fValIDRefs = null; 376 private DatatypeValidator fValENTITY = null; 377 private DatatypeValidator fValENTITIES = null; 378 private DatatypeValidator fValNMTOKEN = null; 379 private DatatypeValidator fValNMTOKENS = null; 380 private DatatypeValidator fValNOTATION = null; 381 382 384 398 protected XPathMatcherStack fMatcherStack = new XPathMatcherStack(); 399 400 401 protected ValueStoreCache fValueStoreCache = new ValueStoreCache(); 402 403 protected SubstitutionGroupComparator fSGComparator = null; 405 406 protected Hashtable UPACheckedGrammarURIs = new Hashtable (); 408 protected static Object fgNullObject = new Object (); 409 410 414 415 public XMLValidator(StringPool stringPool, 416 XMLErrorReporter errorReporter, 417 DefaultEntityHandler entityHandler, 418 XMLDocumentScanner documentScanner) { 419 420 fStringPool = stringPool; 422 fErrorReporter = errorReporter; 423 fEntityHandler = entityHandler; 424 fDocumentScanner = documentScanner; 425 426 fValidateEntity.setDatatypeObject(new Object []{entityHandler, stringPool}); 427 fValidateIDRef.setDatatypeObject(fIdREFDefs); 428 fCheckIDRef.setDatatypeObject(new Object []{fIdDefs, fIdREFDefs}); 429 430 fEmptyURI = fStringPool.addSymbol(""); 431 fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI); 432 fAttrList = new XMLAttrList(fStringPool); 434 entityHandler.setEventHandler(this); 435 entityHandler.setCharDataHandler(this); 436 fDocumentScanner.setEventHandler(this); 437 438 for (int i = 0; i < sizeQNameParts; i++) { 439 fElementQNamePartsStack[i] = new QName(); 440 } 441 init(); 442 443 } 445 public void setGrammarResolver(GrammarResolver grammarResolver){ 446 fGrammarResolver = grammarResolver; 447 } 448 449 453 455 456 public void initHandlers(boolean sendCharDataAsCharArray, 457 XMLDocumentHandler docHandler, 458 XMLDocumentHandler.DTDHandler dtdHandler) { 459 460 fSendCharDataAsCharArray = sendCharDataAsCharArray; 461 fEntityHandler.setSendCharDataAsCharArray(fSendCharDataAsCharArray); 462 fDocumentHandler = docHandler; 463 fDTDHandler = dtdHandler; 464 465 } 467 468 public void resetOrCopy(StringPool stringPool) throws Exception { 469 fAttrList = new XMLAttrList(stringPool); 470 resetCommon(stringPool); 471 } 472 473 474 public void reset(StringPool stringPool) throws Exception { 475 fAttrList.reset(stringPool); 476 resetCommon(stringPool); 477 } 478 479 480 482 492 public void setValidationEnabled(boolean flag) throws Exception { 493 fValidationEnabled = flag; 494 fValidationEnabledByDynamic = false; 495 if (fValidationEnabled) { 496 if (fDynamicDisabledByValidation) { 497 fDynamicValidation = true; 498 fDynamicDisabledByValidation = false; 499 } 500 } else if (fDynamicValidation) { 501 fDynamicValidation = false; 502 fDynamicDisabledByValidation = true; 503 } 504 fValidating = fValidationEnabled; 505 if (fValidating) { 506 initDataTypeValidators(); 507 } 508 } 509 510 511 public boolean getValidationEnabled() { 512 return fValidationEnabled; 513 } 514 515 516 public void setSchemaValidationEnabled(boolean flag) { 517 fSchemaValidation = flag; 518 } 519 520 521 public boolean getSchemaValidationEnabled() { 522 return fSchemaValidation; 523 } 524 525 526 public void setSchemaFullCheckingEnabled(boolean flag) { 527 fSchemaValidationFullChecking = flag; 528 } 529 530 public void setExternalSchemas(Object value){ 534 fExternalSchemas = (String )value; 535 } 536 public void setExternalNoNamespaceSchema(Object value){ 537 fExternalNoNamespaceSchema = (String )value; 538 } 539 540 public String getExternalSchemas(){ 541 return fExternalSchemas; 542 } 543 public String getExternalNoNamespaceSchema(){ 544 return fExternalNoNamespaceSchema; 545 } 546 547 548 public boolean getSchemaFullCheckingEnabled() { 549 return fSchemaValidationFullChecking; 550 } 551 552 553 public void setDynamicValidationEnabled(boolean flag) throws Exception { 554 fDynamicValidation = flag; 555 fDynamicDisabledByValidation = false; 556 if (!fDynamicValidation) { 557 if (fValidationEnabledByDynamic) { 558 fValidationEnabled = false; 559 fValidationEnabledByDynamic = false; 560 } 561 } else if (!fValidationEnabled) { 562 fValidationEnabled = true; 563 fValidationEnabledByDynamic = true; 564 } 565 fValidating = fValidationEnabled; 566 if (fValidating) { 567 initDataTypeValidators(); 568 } 569 } 570 571 572 public boolean getDynamicValidationEnabled() { 573 return fDynamicValidation; 574 } 575 576 577 public void setNormalizeAttributeValues(boolean normalize){ 578 fNormalizeAttributeValues = normalize; 579 } 580 581 582 public void setLoadDTDGrammar(boolean loadDG){ 583 if (fValidating) { 584 fLoadDTDGrammar = true; 585 } else { 586 fLoadDTDGrammar = loadDG; 587 } 588 } 589 590 591 public boolean getLoadDTDGrammar() { 592 return fLoadDTDGrammar; 593 } 594 595 596 public void setNamespacesEnabled(boolean flag) { 597 fNamespacesEnabled = flag; 598 } 599 600 601 public boolean getNamespacesEnabled() { 602 return fNamespacesEnabled; 603 } 604 605 606 public void setWarningOnDuplicateAttDef(boolean flag) { 607 fWarningOnDuplicateAttDef = flag; 608 } 609 610 611 public boolean getWarningOnDuplicateAttDef() { 612 return fWarningOnDuplicateAttDef; 613 } 614 615 616 public void setWarningOnUndeclaredElements(boolean flag) { 617 fWarningOnUndeclaredElements = flag; 618 } 619 620 621 public boolean getWarningOnUndeclaredElements() { 622 return fWarningOnUndeclaredElements; 623 } 624 625 626 public void setNormalizeContents(boolean normalize){ 627 fNormalizeContents = normalize; 628 } 629 public boolean getNormalizeConents() { 630 return fNormalizeContents; 631 } 632 633 637 644 public void startValueScopeFor(IdentityConstraint identityConstraint) 645 throws Exception { 646 647 for(int i=0; i<identityConstraint.getFieldCount(); i++) { 648 Field field = identityConstraint.getFieldAt(i); 649 ValueStoreBase valueStore = fValueStoreCache.getValueStoreFor(field); 650 valueStore.startValueScope(); 651 } 652 653 } 655 661 public XPathMatcher activateField(Field field) throws Exception { 662 if (DEBUG_IDENTITY_CONSTRAINTS) { 663 System.out.println("<IC>: activateField(\""+field+"\")"); 664 } 665 ValueStore valueStore = fValueStoreCache.getValueStoreFor(field); 666 field.setMayMatch(true); 667 XPathMatcher matcher = field.createMatcher(valueStore); 668 fMatcherStack.addMatcher(matcher); 669 matcher.startDocumentFragment(fStringPool); 670 return matcher; 671 } 673 678 public void endValueScopeFor(IdentityConstraint identityConstraint) 679 throws Exception { 680 681 ValueStoreBase valueStore = fValueStoreCache.getValueStoreFor(identityConstraint); 682 valueStore.endValueScope(); 683 684 } 686 690 691 public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception { 692 fDocumentHandler.startEntityReference(entityName, entityType, entityContext); 693 } 694 695 696 public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception { 697 fDocumentHandler.endEntityReference(entityName, entityType, entityContext); 698 } 699 700 701 public void sendEndOfInputNotifications(int entityName, boolean moreToFollow) throws Exception { 702 fDocumentScanner.endOfInput(entityName, moreToFollow); 703 708 } 709 710 711 public void sendReaderChangeNotifications(XMLEntityHandler.EntityReader reader, int readerId) throws Exception { 712 fDocumentScanner.readerChange(reader, readerId); 713 718 } 719 720 721 public boolean externalEntityStandaloneCheck() { 722 return(fStandaloneReader != -1 && fValidating); 723 } 724 725 726 public boolean getValidating() { 727 return fValidating; 728 } 729 730 734 private String normalizeValue (String unNormalizedValue){ 735 fUnnormalizedStr.setLength(0); 736 fUnnormalizedStr.append(unNormalizedValue); 737 normalizeWhitespace(fUnnormalizedStr, (fWhiteSpace == DatatypeValidator.COLLAPSE)); 738 return fNormalizedStr.toString(); 739 } 740 741 755 756 private int normalizeWhitespace( StringBuffer chars, boolean collapse) { 757 int length = fUnnormalizedStr.length(); 758 fNormalizedStr.setLength(0); 759 boolean skipSpace = collapse; 760 boolean sawNonWS = false; 761 int leading = 0; 762 int trailing = 0; 763 int c; 764 for (int i = 0; i < length; i++) { 765 c = chars.charAt(i); 766 if (c == 0x20 || c == 0x0D || c == 0x0A || c == 0x09) { 767 if (!skipSpace) { 768 fNormalizedStr.append(' '); 770 skipSpace = collapse; 771 } 772 if (!sawNonWS) { 773 leading = 1; 775 } 776 } 777 else { 778 fNormalizedStr.append((char)c); 779 skipSpace = false; 780 sawNonWS = true; 781 } 782 } 783 if (skipSpace) { 784 c = fNormalizedStr.length(); 785 if ( c != 0) { 786 fNormalizedStr.setLength (--c); 788 trailing = 2; 789 } 790 else if (leading != 0 && !sawNonWS) { 791 trailing = 2; 794 } 795 } 796 return collapse ? leading + trailing : 0; 798 } 799 800 801 public void processCharacters(char[] chars, int offset, int length) throws Exception { 802 if (DEBUG_NORMALIZATION) { 803 System.out.println("==>processCharacters(char[] chars, int offset, int length"); 804 } 805 if (fValidating) { 806 if (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) { 807 if (DEBUG_NORMALIZATION) { 808 System.out.println("==>char
|