1 16 17 package com.sun.org.apache.xerces.internal.jaxp.validation; 18 19 import java.io.IOException ; 20 import java.util.Enumeration ; 21 import java.util.Locale ; 22 23 import javax.xml.parsers.DocumentBuilder ; 24 import javax.xml.parsers.DocumentBuilderFactory ; 25 import javax.xml.parsers.ParserConfigurationException ; 26 import javax.xml.transform.Result ; 27 import javax.xml.transform.Source ; 28 import javax.xml.transform.dom.DOMResult ; 29 import javax.xml.transform.dom.DOMSource ; 30 31 import com.sun.org.apache.xerces.internal.impl.Constants; 32 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter; 33 import com.sun.org.apache.xerces.internal.impl.validation.EntityState; 34 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; 35 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator; 36 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator; 37 import com.sun.org.apache.xerces.internal.util.NamespaceSupport; 38 import com.sun.org.apache.xerces.internal.util.SymbolTable; 39 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; 40 import com.sun.org.apache.xerces.internal.util.XMLSymbols; 41 import com.sun.org.apache.xerces.internal.xni.NamespaceContext; 42 import com.sun.org.apache.xerces.internal.xni.QName; 43 import com.sun.org.apache.xerces.internal.xni.XMLString; 44 import com.sun.org.apache.xerces.internal.xni.XNIException; 45 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException; 46 import org.w3c.dom.Attr ; 47 import org.w3c.dom.CDATASection ; 48 import org.w3c.dom.Comment ; 49 import org.w3c.dom.Document ; 50 import org.w3c.dom.DocumentType ; 51 import org.w3c.dom.Entity ; 52 import org.w3c.dom.NamedNodeMap ; 53 import org.w3c.dom.Node ; 54 import org.w3c.dom.ProcessingInstruction ; 55 import org.w3c.dom.Text ; 56 import org.xml.sax.SAXException ; 57 58 64 final class DOMValidatorHelper implements ValidatorHelper, EntityState { 65 66 70 71 private static final int CHUNK_SIZE = (1 << 10); 72 73 74 private static final int CHUNK_MASK = CHUNK_SIZE - 1; 75 76 78 79 private static final String ERROR_REPORTER = 80 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 81 82 83 private static final String NAMESPACE_CONTEXT = 84 Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY; 85 86 87 private static final String SCHEMA_VALIDATOR = 88 Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY; 89 90 91 private static final String SYMBOL_TABLE = 92 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 93 94 95 private static final String VALIDATION_MANAGER = 96 Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY; 97 98 102 103 private XMLErrorReporter fErrorReporter; 104 105 106 private NamespaceSupport fNamespaceContext; 107 108 109 private DOMNamespaceContext fDOMNamespaceContext = new DOMNamespaceContext(); 110 111 112 private XMLSchemaValidator fSchemaValidator; 113 114 115 private SymbolTable fSymbolTable; 116 117 118 private ValidationManager fValidationManager; 119 120 121 private XMLSchemaValidatorComponentManager fComponentManager; 122 123 124 private final SimpleLocator fXMLLocator = new SimpleLocator(null, null, -1, -1, -1); 125 126 127 private DOMDocumentHandler fDOMValidatorHandler; 128 129 130 private final DOMResultAugmentor fDOMResultAugmentor = new DOMResultAugmentor(this); 131 132 133 private final DOMResultBuilder fDOMResultBuilder = new DOMResultBuilder(); 134 135 136 private NamedNodeMap fEntities = null; 137 138 139 private char [] fCharBuffer = new char[CHUNK_SIZE]; 140 141 142 private Node fRoot; 143 144 145 private Node fCurrentElement; 146 147 148 final QName fElementQName = new QName(); 149 final QName fAttributeQName = new QName(); 150 final XMLAttributesImpl fAttributes = new XMLAttributesImpl(); 151 final XMLString fTempString = new XMLString(); 152 153 public DOMValidatorHelper(XMLSchemaValidatorComponentManager componentManager) { 154 fComponentManager = componentManager; 155 fErrorReporter = (XMLErrorReporter) fComponentManager.getProperty(ERROR_REPORTER); 156 fNamespaceContext = (NamespaceSupport) fComponentManager.getProperty(NAMESPACE_CONTEXT); 157 fSchemaValidator = (XMLSchemaValidator) fComponentManager.getProperty(SCHEMA_VALIDATOR); 158 fSymbolTable = (SymbolTable) fComponentManager.getProperty(SYMBOL_TABLE); 159 fValidationManager = (ValidationManager) fComponentManager.getProperty(VALIDATION_MANAGER); 160 } 161 162 165 166 public void validate(Source source, Result result) 167 throws SAXException , IOException { 168 if (result instanceof DOMResult || result == null) { 169 final DOMSource domSource = (DOMSource ) source; 170 final DOMResult domResult = (DOMResult ) result; 171 Node node = domSource.getNode(); 172 fRoot = node; 173 if (node != null) { 174 fComponentManager.reset(); 175 fValidationManager.setEntityState(this); 176 fDOMNamespaceContext.reset(); 177 String systemId = domSource.getSystemId(); 178 fXMLLocator.setLiteralSystemId(systemId); 179 fXMLLocator.setExpandedSystemId(systemId); 180 fErrorReporter.setDocumentLocator(fXMLLocator); 181 try { 182 setupEntityMap((node.getNodeType() == Node.DOCUMENT_NODE) ? (Document ) node : node.getOwnerDocument()); 184 setupDOMResultHandler(domSource, domResult); 185 fSchemaValidator.startDocument(fXMLLocator, null, fDOMNamespaceContext, null); 186 validate(node); 187 fSchemaValidator.endDocument(null); 188 } 189 catch (XMLParseException e) { 190 throw Util.toSAXParseException(e); 191 } 192 catch (XNIException e) { 193 throw Util.toSAXException(e); 194 } 195 finally { 196 fRoot = null; 198 fCurrentElement = null; 199 fEntities = null; 200 if (fDOMValidatorHandler != null) { 201 fDOMValidatorHandler.setDOMResult(null); 202 } 203 } 204 } 205 return; 206 } 207 throw new IllegalArgumentException (JAXPValidationMessageFormatter.formatMessage(Locale.getDefault(), 208 "SourceResultMismatch", 209 new Object [] {source.getClass().getName(), result.getClass().getName()})); 210 } 211 212 215 216 public boolean isEntityDeclared(String name) { 217 return false; 218 } 219 220 public boolean isEntityUnparsed(String name) { 221 if (fEntities != null) { 222 Entity entity = (Entity ) fEntities.getNamedItem(name); 223 if (entity != null) { 224 return (entity.getNotationName() != null); 225 } 226 } 227 return false; 228 } 229 230 233 234 235 private void validate(Node node) { 236 final Node top = node; 237 while (node != null) { 240 beginNode(node); 241 Node next = node.getFirstChild(); 242 while (next == null) { 243 finishNode(node); 244 if (top == node) { 245 break; 246 } 247 next = node.getNextSibling(); 248 if (next == null) { 249 node = node.getParentNode(); 250 if (node == null || top == node) { 251 if (node != null) { 252 finishNode(node); 253 } 254 next = null; 255 break; 256 } 257 } 258 } 259 node = next; 260 } 261 } 262 263 264 private void beginNode(Node node) { 265 switch (node.getNodeType()) { 266 case Node.ELEMENT_NODE: 267 fCurrentElement = node; 268 fNamespaceContext.pushContext(); 270 fillQName(fElementQName, node); 272 processAttributes(node.getAttributes()); 273 fSchemaValidator.startElement(fElementQName, fAttributes, null); 274 break; 275 case Node.TEXT_NODE: 276 if (fDOMValidatorHandler != null) { 277 fDOMValidatorHandler.setIgnoringCharacters(true); 278 sendCharactersToValidator(node.getNodeValue()); 279 fDOMValidatorHandler.setIgnoringCharacters(false); 280 fDOMValidatorHandler.characters((Text ) node); 281 } 282 else { 283 sendCharactersToValidator(node.getNodeValue()); 284 } 285 break; 286 case Node.CDATA_SECTION_NODE: 287 if (fDOMValidatorHandler != null) { 288 fDOMValidatorHandler.setIgnoringCharacters(true); 289 fSchemaValidator.startCDATA(null); 290 sendCharactersToValidator(node.getNodeValue()); 291 fSchemaValidator.endCDATA(null); 292 fDOMValidatorHandler.setIgnoringCharacters(false); 293 fDOMValidatorHandler.cdata((CDATASection ) node); 294 } 295 else { 296 fSchemaValidator.startCDATA(null); 297 sendCharactersToValidator(node.getNodeValue()); 298 fSchemaValidator.endCDATA(null); 299 } 300 break; 301 case Node.PROCESSING_INSTRUCTION_NODE: 302 306 if (fDOMValidatorHandler != null) { 307 fDOMValidatorHandler.processingInstruction((ProcessingInstruction ) node); 308 } 309 break; 310 case Node.COMMENT_NODE: 311 315 if (fDOMValidatorHandler != null) { 316 fDOMValidatorHandler.comment((Comment ) node); 317 } 318 break; 319 case Node.DOCUMENT_TYPE_NODE: 320 323 if (fDOMValidatorHandler != null) { 324 fDOMValidatorHandler.doctypeDecl((DocumentType ) node); 325 } 326 break; 327 default: break; 329 } 330 } 331 332 333 private void finishNode(Node node) { 334 if (node.getNodeType() == Node.ELEMENT_NODE) { 335 fCurrentElement = node; 336 fillQName(fElementQName, node); 338 fSchemaValidator.endElement(fElementQName, null); 339 fNamespaceContext.popContext(); 341 } 342 } 343 344 349 private void setupEntityMap(Document doc) { 350 if (doc != null) { 351 DocumentType docType = doc.getDoctype(); 352 if (docType != null) { 353 fEntities = docType.getEntities(); 354 return; 355 } 356 } 357 fEntities = null; 358 } 359 360 363 private void setupDOMResultHandler(DOMSource source, DOMResult result) throws SAXException { 364 if (result == null) { 366 fDOMValidatorHandler = null; 367 fSchemaValidator.setDocumentHandler(null); 368 return; 369 } 370 final Node nodeResult = result.getNode(); 371 if (source.getNode() == nodeResult) { 374 fDOMValidatorHandler = fDOMResultAugmentor; 375 fDOMResultAugmentor.setDOMResult(result); 376 fSchemaValidator.setDocumentHandler(fDOMResultAugmentor); 377 return; 378 } 379 if (result.getNode() == null) { 380 try { 381 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 382 factory.setNamespaceAware(true); 383 DocumentBuilder builder = factory.newDocumentBuilder(); 384 result.setNode(builder.newDocument()); 385 } 386 catch (ParserConfigurationException e) { 387 throw new SAXException (e); 388 } 389 } 390 fDOMValidatorHandler = fDOMResultBuilder; 391 fDOMResultBuilder.setDOMResult(result); 392 fSchemaValidator.setDocumentHandler(fDOMResultBuilder); 393 } 394 395 private void fillQName(QName toFill, Node node) { 396 final String prefix = node.getPrefix(); 397 final String localName = node.getLocalName(); 398 final String rawName = node.getNodeName(); 399 final String namespace = node.getNamespaceURI(); 400 401 toFill.uri = (namespace != null && namespace.length() > 0) ? fSymbolTable.addSymbol(namespace) : null; 402 toFill.rawname = (rawName != null) ? fSymbolTable.addSymbol(rawName) : XMLSymbols.EMPTY_STRING; 403 404 if (localName == null) { 406 int k = rawName.indexOf(':'); 407 if (k > 0) { 408 toFill.prefix = fSymbolTable.addSymbol(rawName.substring(0, k)); 409 toFill.localpart = fSymbolTable.addSymbol(rawName.substring(k + 1)); 410 } 411 else { 412 toFill.prefix = XMLSymbols.EMPTY_STRING; 413 toFill.localpart = toFill.rawname; 414 } 415 } 416 else { 417 toFill.prefix = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING; 418 toFill.localpart = (localName != null) ? fSymbolTable.addSymbol(localName) : XMLSymbols.EMPTY_STRING; 419 } 420 } 421 422 private void processAttributes(NamedNodeMap attrMap) { 423 final int attrCount = attrMap.getLength(); 424 fAttributes.removeAllAttributes(); 425 for (int i = 0; i < attrCount; ++i) { 426 Attr attr = (Attr ) attrMap.item(i); 427 String value = attr.getValue(); 428 if (value == null) { 429 value = XMLSymbols.EMPTY_STRING; 430 } 431 fillQName(fAttributeQName, attr); 432 fAttributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, value); 434 fAttributes.setSpecified(i, attr.getSpecified()); 435 if (fAttributeQName.uri == NamespaceContext.XMLNS_URI) { 439 if (fAttributeQName.prefix == XMLSymbols.PREFIX_XMLNS) { 441 fNamespaceContext.declarePrefix(fAttributeQName.localpart, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 442 } 443 else { 444 fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 445 } 446 } 447 } 448 } 449 450 private void sendCharactersToValidator(String str) { 451 if (str != null) { 452 final int length = str.length(); 453 final int remainder = length & CHUNK_MASK; 454 if (remainder > 0) { 455 str.getChars(0, remainder, fCharBuffer, 0); 456 fTempString.setValues(fCharBuffer, 0, remainder); 457 fSchemaValidator.characters(fTempString, null); 458 } 459 int i = remainder; 460 while (i < length) { 461 str.getChars(i, i += CHUNK_SIZE, fCharBuffer, 0); 462 fTempString.setValues(fCharBuffer, 0, CHUNK_SIZE); 463 fSchemaValidator.characters(fTempString, null); 464 } 465 } 466 } 467 468 Node getCurrentElement() { 469 return fCurrentElement; 470 } 471 472 475 final class DOMNamespaceContext implements NamespaceContext { 476 477 481 486 protected String [] fNamespace = new String [16 * 2]; 487 488 489 protected int fNamespaceSize = 0; 490 491 495 protected boolean fDOMContextBuilt = false; 496 497 501 public void pushContext() { 502 fNamespaceContext.pushContext(); 503 } 504 505 public void popContext() { 506 fNamespaceContext.popContext(); 507 } 508 509 public boolean declarePrefix(String prefix, String uri) { 510 return fNamespaceContext.declarePrefix(prefix, uri); 511 } 512 513 public String getURI(String prefix) { 514 String uri = fNamespaceContext.getURI(prefix); 515 if (uri == null) { 516 if (!fDOMContextBuilt) { 517 fillNamespaceContext(); 518 fDOMContextBuilt = true; 519 } 520 if (fNamespaceSize > 0 && 521 !fNamespaceContext.containsPrefix(prefix)) { 522 uri = getURI0(prefix); 523 } 524 } 525 return uri; 526 } 527 528 public String getPrefix(String uri) { 529 return fNamespaceContext.getPrefix(uri); 530 } 531 532 public int getDeclaredPrefixCount() { 533 return fNamespaceContext.getDeclaredPrefixCount(); 534 } 535 536 public String getDeclaredPrefixAt(int index) { 537 return fNamespaceContext.getDeclaredPrefixAt(index); 538 } 539 540 public Enumeration getAllPrefixes() { 541 return fNamespaceContext.getAllPrefixes(); 542 } 543 544 public void reset() { 545 fDOMContextBuilt = false; 546 fNamespaceSize = 0; 547 } 548 549 private void fillNamespaceContext() { 550 if (fRoot != null) { 551 Node currentNode = fRoot.getParentNode(); 552 while (currentNode != null) { 553 if (Node.ELEMENT_NODE == currentNode.getNodeType()) { 554 NamedNodeMap attributes = currentNode.getAttributes(); 555 final int attrCount = attributes.getLength(); 556 for (int i = 0; i < attrCount; ++i) { 557 Attr attr = (Attr ) attributes.item(i); 558 String value = attr.getValue(); 559 if (value == null) { 560 value = XMLSymbols.EMPTY_STRING; 561 } 562 fillQName(fAttributeQName, attr); 563 if (fAttributeQName.uri == NamespaceContext.XMLNS_URI) { 567 if (fAttributeQName.prefix == XMLSymbols.PREFIX_XMLNS) { 569 declarePrefix0(fAttributeQName.localpart, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 570 } 571 else { 572 declarePrefix0(XMLSymbols.EMPTY_STRING, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 573 } 574 } 575 } 576 577 } 578 currentNode = currentNode.getParentNode(); 579 } 580 } 581 } 582 583 private void declarePrefix0(String prefix, String uri) { 584 if (fNamespaceSize == fNamespace.length) { 586 String [] namespacearray = new String [fNamespaceSize * 2]; 587 System.arraycopy(fNamespace, 0, namespacearray, 0, fNamespaceSize); 588 fNamespace = namespacearray; 589 } 590 591 fNamespace[fNamespaceSize++] = prefix; 593 fNamespace[fNamespaceSize++] = uri; 594 } 595 596 private String getURI0(String prefix) { 597 for (int i = 0; i < fNamespaceSize; i += 2) { 599 if (fNamespace[i] == prefix) { 600 return fNamespace[i + 1]; 601 } 602 } 603 return null; 605 } 606 } 607 608 } | Popular Tags |