1 16 17 package org.apache.xerces.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 org.apache.xerces.impl.Constants; 32 import org.apache.xerces.impl.XMLErrorReporter; 33 import org.apache.xerces.impl.validation.EntityState; 34 import org.apache.xerces.impl.validation.ValidationManager; 35 import org.apache.xerces.impl.xs.XMLSchemaValidator; 36 import org.apache.xerces.impl.xs.util.SimpleLocator; 37 import org.apache.xerces.util.NamespaceSupport; 38 import org.apache.xerces.util.SymbolTable; 39 import org.apache.xerces.util.XMLAttributesImpl; 40 import org.apache.xerces.util.XMLSymbols; 41 import org.apache.xerces.xni.NamespaceContext; 42 import org.apache.xerces.xni.QName; 43 import org.apache.xerces.xni.XMLString; 44 import org.apache.xerces.xni.XNIException; 45 import org.apache.xerces.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 toFill.prefix = (prefix != null) ? fSymbolTable.addSymbol(prefix) : XMLSymbols.EMPTY_STRING; 401 toFill.localpart = (localName != null) ? fSymbolTable.addSymbol(localName) : XMLSymbols.EMPTY_STRING; 402 toFill.rawname = (rawName != null) ? fSymbolTable.addSymbol(rawName) : XMLSymbols.EMPTY_STRING; 403 toFill.uri = (namespace != null && namespace.length() > 0) ? fSymbolTable.addSymbol(namespace) : null; 404 } 405 406 private void processAttributes(NamedNodeMap attrMap) { 407 final int attrCount = attrMap.getLength(); 408 fAttributes.removeAllAttributes(); 409 for (int i = 0; i < attrCount; ++i) { 410 Attr attr = (Attr ) attrMap.item(i); 411 String value = attr.getValue(); 412 if (value == null) { 413 value = XMLSymbols.EMPTY_STRING; 414 } 415 fillQName(fAttributeQName, attr); 416 fAttributes.addAttributeNS(fAttributeQName, XMLSymbols.fCDATASymbol, value); 418 fAttributes.setSpecified(i, attr.getSpecified()); 419 if (fAttributeQName.uri == NamespaceContext.XMLNS_URI) { 423 if (fAttributeQName.prefix == XMLSymbols.PREFIX_XMLNS) { 425 fNamespaceContext.declarePrefix(fAttributeQName.localpart, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 426 } 427 else { 428 fNamespaceContext.declarePrefix(XMLSymbols.EMPTY_STRING, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 429 } 430 } 431 } 432 } 433 434 private void sendCharactersToValidator(String str) { 435 if (str != null) { 436 final int length = str.length(); 437 final int remainder = length & CHUNK_MASK; 438 if (remainder > 0) { 439 str.getChars(0, remainder, fCharBuffer, 0); 440 fTempString.setValues(fCharBuffer, 0, remainder); 441 fSchemaValidator.characters(fTempString, null); 442 } 443 int i = remainder; 444 while (i < length) { 445 str.getChars(i, i += CHUNK_SIZE, fCharBuffer, 0); 446 fTempString.setValues(fCharBuffer, 0, CHUNK_SIZE); 447 fSchemaValidator.characters(fTempString, null); 448 } 449 } 450 } 451 452 Node getCurrentElement() { 453 return fCurrentElement; 454 } 455 456 459 final class DOMNamespaceContext implements NamespaceContext { 460 461 465 470 protected String [] fNamespace = new String [16 * 2]; 471 472 473 protected int fNamespaceSize = 0; 474 475 479 protected boolean fDOMContextBuilt = false; 480 481 485 public void pushContext() { 486 fNamespaceContext.pushContext(); 487 } 488 489 public void popContext() { 490 fNamespaceContext.popContext(); 491 } 492 493 public boolean declarePrefix(String prefix, String uri) { 494 return fNamespaceContext.declarePrefix(prefix, uri); 495 } 496 497 public String getURI(String prefix) { 498 String uri = fNamespaceContext.getURI(prefix); 499 if (uri == null) { 500 if (!fDOMContextBuilt) { 501 fillNamespaceContext(); 502 fDOMContextBuilt = true; 503 } 504 if (fNamespaceSize > 0 && 505 !fNamespaceContext.containsPrefix(prefix)) { 506 uri = getURI0(prefix); 507 } 508 } 509 return uri; 510 } 511 512 public String getPrefix(String uri) { 513 return fNamespaceContext.getPrefix(uri); 514 } 515 516 public int getDeclaredPrefixCount() { 517 return fNamespaceContext.getDeclaredPrefixCount(); 518 } 519 520 public String getDeclaredPrefixAt(int index) { 521 return fNamespaceContext.getDeclaredPrefixAt(index); 522 } 523 524 public Enumeration getAllPrefixes() { 525 return fNamespaceContext.getAllPrefixes(); 526 } 527 528 public void reset() { 529 fDOMContextBuilt = false; 530 fNamespaceSize = 0; 531 } 532 533 private void fillNamespaceContext() { 534 if (fRoot != null) { 535 Node currentNode = fRoot.getParentNode(); 536 while (currentNode != null) { 537 if (Node.ELEMENT_NODE == currentNode.getNodeType()) { 538 NamedNodeMap attributes = currentNode.getAttributes(); 539 final int attrCount = attributes.getLength(); 540 for (int i = 0; i < attrCount; ++i) { 541 Attr attr = (Attr ) attributes.item(i); 542 String value = attr.getValue(); 543 if (value == null) { 544 value = XMLSymbols.EMPTY_STRING; 545 } 546 fillQName(fAttributeQName, attr); 547 if (fAttributeQName.uri == NamespaceContext.XMLNS_URI) { 551 if (fAttributeQName.prefix == XMLSymbols.PREFIX_XMLNS) { 553 declarePrefix0(fAttributeQName.localpart, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 554 } 555 else { 556 declarePrefix0(XMLSymbols.EMPTY_STRING, value.length() != 0 ? fSymbolTable.addSymbol(value) : null); 557 } 558 } 559 } 560 561 } 562 currentNode = currentNode.getParentNode(); 563 } 564 } 565 } 566 567 private void declarePrefix0(String prefix, String uri) { 568 if (fNamespaceSize == fNamespace.length) { 570 String [] namespacearray = new String [fNamespaceSize * 2]; 571 System.arraycopy(fNamespace, 0, namespacearray, 0, fNamespaceSize); 572 fNamespace = namespacearray; 573 } 574 575 fNamespace[fNamespaceSize++] = prefix; 577 fNamespace[fNamespaceSize++] = uri; 578 } 579 580 private String getURI0(String prefix) { 581 for (int i = 0; i < fNamespaceSize; i += 2) { 583 if (fNamespace[i] == prefix) { 584 return fNamespace[i + 1]; 585 } 586 } 587 return null; 589 } 590 } 591 592 } | Popular Tags |