1 7 package org.jboss.xml.binding.parser.xni; 8 9 import org.jboss.xml.binding.parser.JBossXBParser; 10 import org.jboss.xml.binding.JBossXBException; 11 import org.jboss.xml.binding.Unmarshaller; 12 import org.jboss.xml.binding.AttributesImpl; 13 import org.jboss.logging.Logger; 14 import org.apache.xerces.parsers.IntegratedParserConfiguration; 15 import org.apache.xerces.parsers.XMLDocumentParser; 16 import org.apache.xerces.util.SymbolTable; 17 import org.apache.xerces.xni.grammars.XMLGrammarPool; 18 import org.apache.xerces.xni.parser.XMLComponentManager; 19 import org.apache.xerces.xni.parser.XMLParserConfiguration; 20 import org.apache.xerces.xni.parser.XMLErrorHandler; 21 import org.apache.xerces.xni.parser.XMLParseException; 22 import org.apache.xerces.xni.parser.XMLInputSource; 23 import org.apache.xerces.xni.parser.XMLEntityResolver; 24 import org.apache.xerces.xni.XNIException; 25 import org.apache.xerces.xni.NamespaceContext; 26 import org.apache.xerces.xni.XMLLocator; 27 import org.apache.xerces.xni.Augmentations; 28 import org.apache.xerces.xni.XMLAttributes; 29 import org.apache.xerces.xni.XMLString; 30 import org.apache.xerces.xni.QName; 31 import org.apache.xerces.xni.XMLResourceIdentifier; 32 import org.apache.xerces.impl.xs.XSMessageFormatter; 33 import org.apache.xerces.impl.xs.JBossXBSchemaValidator; 34 import org.apache.xerces.xs.XSElementDeclaration; 35 import org.apache.xerces.xs.XSTypeDefinition; 36 import org.xml.sax.EntityResolver ; 37 import org.xml.sax.SAXException ; 38 import org.xml.sax.InputSource ; 39 40 import java.io.Reader ; 41 import java.io.IOException ; 42 import java.io.InputStream ; 43 44 45 49 public class XniJBossXBParser 50 implements JBossXBParser 51 { 52 private static final Logger log = Logger.getLogger(XniJBossXBParser.class); 53 private final XMLParserConfiguration config; 54 private final DocumentParser parser; 55 private JBossXBParser.ContentHandler contentHandler; 56 57 public XniJBossXBParser() 58 { 59 config = new ParserConfiguration(); 60 parser = new DocumentParser(config); 61 62 config.setErrorHandler(new XMLErrorHandler() 63 { 64 public void warning(String domain, String key, XMLParseException exception) throws XNIException 65 { 66 log.warn("domain=" + domain + ", key=" + key + ": " + exception.getMessage()); 67 } 68 69 public void error(String domain, String key, XMLParseException exception) throws XNIException 70 { 71 log.error("domain=" + domain + ", key=" + key + ": " + exception.getMessage()); 72 throw exception; 73 } 74 75 public void fatalError(String domain, String key, XMLParseException exception) throws XNIException 76 { 77 log.error("domain=" + domain + ", key=" + key + ": " + exception.getMessage()); 78 throw exception; 79 } 80 } 81 ); 82 83 config.setFeature(Unmarshaller.NAMESPACES, true); 84 config.setFeature(Unmarshaller.VALIDATION, true); 85 config.setFeature(Unmarshaller.SCHEMA_VALIDATION, true); 86 config.setFeature(Unmarshaller.SCHEMA_FULL_CHECKING, true); 87 config.setFeature(Unmarshaller.DYNAMIC_VALIDATION, true); 88 } 89 90 public void setEntityResolver(final EntityResolver entityResolver) throws JBossXBException 91 { 92 config.setEntityResolver(new XMLEntityResolver() 93 { 94 private EntityResolver resolver; 95 96 { 97 this.resolver = entityResolver; 98 } 99 100 public XMLInputSource resolveEntity(XMLResourceIdentifier resId) throws XNIException, 101 IOException 102 { 103 XMLInputSource result; 104 try 105 { 106 InputSource source = resolver.resolveEntity(resId.getPublicId(), resId.getExpandedSystemId()); 107 if(source != null) 108 { 109 if(source.getCharacterStream() != null) 110 { 111 result = new XMLInputSource(resId.getPublicId(), 112 resId.getExpandedSystemId(), 113 resId.getBaseSystemId(), 114 source.getCharacterStream(), 115 source.getEncoding() 116 ); 117 } 118 else if(source.getByteStream() != null) 119 { 120 result = new XMLInputSource(resId.getPublicId(), 121 resId.getExpandedSystemId(), 122 resId.getBaseSystemId(), 123 source.getByteStream(), 124 source.getEncoding() 125 ); 126 } 127 else if(source.getSystemId() != null) 128 { 129 result = new XMLInputSource(resId.getPublicId(), source.getSystemId(), resId.getBaseSystemId()); 130 } 131 else 132 { 133 throw new IllegalStateException ( 134 "Resolved source contains no about the source, i.e. systemId, byte stream and character stream are all null." 135 ); 136 } 137 } 138 else 139 { 140 result = null; 141 } 142 } 143 catch(SAXException e) 144 { 145 throw new XNIException("Failed to resolve entity: publicId=" + 146 resId.getPublicId() + 147 ", literal systemId=" + 148 resId.getLiteralSystemId() + 149 ", base systemId=" + 150 resId.getBaseSystemId() 151 + ", expanded systemId=" + resId.getExpandedSystemId() 152 ); 153 } 154 return result; 155 } 156 } 157 ); 158 } 159 160 public void setProperty(String name, Object value) throws JBossXBException 161 { 162 config.setProperty(name, value); 163 } 164 165 public void setFeature(String name, boolean value) throws JBossXBException 166 { 167 config.setFeature(name, value); 168 } 169 170 public void parse(String systemId, ContentHandler handler) throws JBossXBException 171 { 172 this.contentHandler = handler; 173 174 XMLInputSource xmlSource = new XMLInputSource(null, systemId, null); 175 try 176 { 177 parser.parse(xmlSource); 178 } 179 catch(Exception e) 180 { 181 throw new JBossXBException("Failed to parse document " + systemId, e); 182 } 183 } 184 185 public void parse(InputStream is, ContentHandler handler) throws JBossXBException 186 { 187 this.contentHandler = handler; 188 189 XMLInputSource xmlSource = new XMLInputSource(null, null, null, is, null); try 191 { 192 parser.parse(xmlSource); 193 } 194 catch(Exception e) 195 { 196 throw new JBossXBException("Failed to parse document", e); 197 } 198 } 199 200 public void parse(Reader reader, ContentHandler handler) throws JBossXBException 201 { 202 this.contentHandler = handler; 203 204 XMLInputSource xmlSource = new XMLInputSource(null, null, null, reader, null); try 206 { 207 parser.parse(xmlSource); 208 } 209 catch(Exception e) 210 { 211 throw new JBossXBException("Failed to parse document", e); 212 } 213 } 214 215 217 class DocumentParser 218 extends XMLDocumentParser 219 { 220 private boolean namespaces; 221 private boolean prefixes; 222 private NamespaceContext namespaceContext; 223 private QName qName = new QName(); 224 private SAXAttributes saxAttrs = new SAXAttributes(); 225 226 public DocumentParser(XMLParserConfiguration config) 227 { 228 super(config); 229 namespaces = config.getFeature(Unmarshaller.NAMESPACES); 230 prefixes = false; 232 } 233 234 public void startDocument(XMLLocator locator, String encoding, 235 NamespaceContext namespaceContext, 236 Augmentations augs) 237 throws XNIException 238 { 239 this.namespaceContext = namespaceContext; 240 } 241 242 public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) 243 throws XNIException 244 { 245 } 246 247 public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) 248 throws XNIException 249 { 250 } 251 252 public void comment(XMLString text, Augmentations augs) throws XNIException 253 { 254 } 255 256 public void processingInstruction(String target, XMLString data, Augmentations augs) 257 throws XNIException 258 { 259 } 260 261 public void startElement(QName name, XMLAttributes attributes, Augmentations augs) 262 throws XNIException 263 { 264 XSTypeDefinition type = null; 265 if(augs != null) 266 { 267 JBossXBSchemaValidator validator = (JBossXBSchemaValidator)augs.getItem("jbossxb.validator"); 268 if(validator != null) 269 { 270 XSElementDeclaration element = validator.getCurrentElementDelcaration(); 271 type = element.getTypeDefinition(); 272 } 273 } 274 275 if(type == null) 276 { 277 if(log.isTraceEnabled()) 278 { 279 log.trace("Type is not available for " + name.rawname); 280 } 281 } 282 283 if(namespaces) 284 { 285 int count = startNamespaceMapping(); 286 287 if(count > 0) 290 { 291 int len = attributes.getLength(); 292 for(int i = len - 1; i >= 0; i--) 293 { 294 attributes.getName(i, qName); 295 296 if((qName.prefix != null && qName.prefix.equals("xmlns")) || 297 qName.rawname.equals("xmlns")) 298 { 299 if(!prefixes) 300 { 301 attributes.removeAttributeAt(i); 302 } 303 else 304 { 305 qName.prefix = ""; 308 qName.uri = ""; 309 qName.localpart = ""; 310 attributes.setName(i, qName); 311 } 312 } 313 } 314 } 315 } 316 317 String uri = name.uri != null ? name.uri : ""; 318 String localpart = namespaces ? name.localpart : ""; 319 saxAttrs.setAttrs(attributes); 320 contentHandler.startElement(uri, localpart, name.rawname, saxAttrs, type); 321 } 322 330 public void startGeneralEntity(String name, 331 XMLResourceIdentifier identifier, 332 String encoding, 333 Augmentations augs) throws XNIException 334 { 335 } 336 337 public void textDecl(String version, String encoding, Augmentations augs) throws XNIException 338 { 339 } 340 341 public void endGeneralEntity(String name, Augmentations augs) throws XNIException 342 { 343 } 344 345 public void characters(XMLString text, Augmentations augs) throws XNIException 346 { 347 int i = text.offset; 350 while(i < text.offset + text.length) 351 { 352 if(!Character.isWhitespace(text.ch[i++])) 353 { 354 contentHandler.characters(text.ch, text.offset, text.length); 355 break; 356 } 357 } 358 } 359 360 public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException 361 { 362 } 363 364 public void endElement(QName element, Augmentations augs) throws XNIException 365 { 366 String uri = element.uri != null ? element.uri : ""; 367 String localpart = namespaces ? element.localpart : ""; 368 contentHandler.endElement(uri, localpart, element.rawname); 369 } 370 371 public void startCDATA(Augmentations augs) throws XNIException 372 { 373 } 374 375 public void endCDATA(Augmentations augs) throws XNIException 376 { 377 } 378 379 public void endDocument(Augmentations augs) throws XNIException 380 { 381 super.endDocument(augs); 382 } 383 384 386 protected final int startNamespaceMapping() 387 { 388 int count = namespaceContext.getDeclaredPrefixCount(); 389 if(count > 0) 390 { 391 String prefix = null; 392 String uri = null; 393 for(int i = 0; i < count; i++) 394 { 395 prefix = namespaceContext.getDeclaredPrefixAt(i); 396 uri = namespaceContext.getURI(prefix); 397 contentHandler.startPrefixMapping(prefix, (uri == null) ? "" : uri); 398 } 399 } 400 return count; 401 } 402 403 private AttributesImpl toSaxAttributes(XMLAttributes attributes) 404 { 405 AttributesImpl attrs = null; 406 if(attributes != null) 407 { 408 attrs = new AttributesImpl(attributes.getLength()); 409 for(int i = 0; i < attributes.getLength(); ++i) 410 { 411 if(!"xmlns".equals(attributes.getPrefix(i))) 412 { 413 attrs.add(attributes.getURI(i), 414 attributes.getLocalName(i), 415 attributes.getQName(i), 416 attributes.getType(i), 417 attributes.getValue(i) 418 ); 419 } 420 } 421 } 422 return attrs; 423 } 424 } 425 426 class ParserConfiguration 427 extends IntegratedParserConfiguration 428 { 429 public ParserConfiguration() 430 { 431 } 432 433 public ParserConfiguration(SymbolTable symbolTable) 434 { 435 super(symbolTable); 436 } 437 438 public ParserConfiguration(SymbolTable symbolTable, XMLGrammarPool grammarPool) 439 { 440 super(symbolTable, grammarPool); 441 } 442 443 public ParserConfiguration(SymbolTable symbolTable, 444 XMLGrammarPool grammarPool, 445 XMLComponentManager parentSettings) 446 { 447 super(symbolTable, grammarPool, parentSettings); 448 } 449 450 protected void configurePipeline() 451 { 452 setProperty(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory); 454 455 configureDTDPipeline(); 457 458 if(fFeatures.get(NAMESPACES) == Boolean.TRUE) 460 { 461 fProperties.put(NAMESPACE_BINDER, fNamespaceBinder); 462 fScanner = fNamespaceScanner; 463 fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner); 464 if(fDTDValidator != null) 465 { 466 fProperties.put(DTD_VALIDATOR, fDTDValidator); 467 fNamespaceScanner.setDTDValidator(fDTDValidator); 468 fNamespaceScanner.setDocumentHandler(fDTDValidator); 469 fDTDValidator.setDocumentSource(fNamespaceScanner); 470 fDTDValidator.setDocumentHandler(fDocumentHandler); 471 if(fDocumentHandler != null) 472 { 473 fDocumentHandler.setDocumentSource(fDTDValidator); 474 } 475 fLastComponent = fDTDValidator; 476 } 477 else 478 { 479 fNamespaceScanner.setDocumentHandler(fDocumentHandler); 480 fNamespaceScanner.setDTDValidator(null); 481 if(fDocumentHandler != null) 482 { 483 fDocumentHandler.setDocumentSource(fNamespaceScanner); 484 } 485 fLastComponent = fNamespaceScanner; 486 } 487 } 488 else 489 { 490 fScanner = fNonNSScanner; 491 fProperties.put(DOCUMENT_SCANNER, fNonNSScanner); 492 if(fNonNSDTDValidator != null) 493 { 494 fProperties.put(DTD_VALIDATOR, fNonNSDTDValidator); 495 fNonNSScanner.setDocumentHandler(fNonNSDTDValidator); 496 fNonNSDTDValidator.setDocumentSource(fNonNSScanner); 497 fNonNSDTDValidator.setDocumentHandler(fDocumentHandler); 498 if(fDocumentHandler != null) 499 { 500 fDocumentHandler.setDocumentSource(fNonNSDTDValidator); 501 } 502 fLastComponent = fNonNSDTDValidator; 503 } 504 else 505 { 506 fScanner.setDocumentHandler(fDocumentHandler); 507 if(fDocumentHandler != null) 508 { 509 fDocumentHandler.setDocumentSource(fScanner); 510 } 511 fLastComponent = fScanner; 512 } 513 } 514 515 if(fFeatures.get(XMLSCHEMA_VALIDATION) == Boolean.TRUE) 517 { 518 if(fSchemaValidator == null) 520 { 521 fSchemaValidator = new JBossXBSchemaValidator(); 522 523 fProperties.put(SCHEMA_VALIDATOR, fSchemaValidator); 525 addComponent(fSchemaValidator); 526 if(fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) 528 { 529 XSMessageFormatter xmft = new XSMessageFormatter(); 530 fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, xmft); 531 } 532 533 } 534 535 fLastComponent.setDocumentHandler(fSchemaValidator); 536 fSchemaValidator.setDocumentSource(fLastComponent); 537 fSchemaValidator.setDocumentHandler(fDocumentHandler); 538 if(fDocumentHandler != null) 539 { 540 fDocumentHandler.setDocumentSource(fSchemaValidator); 541 } 542 fLastComponent = fSchemaValidator; 543 } 544 } 545 } 546 547 private static class SAXAttributes 548 implements org.xml.sax.Attributes 549 { 550 private XMLAttributes attrs; 551 552 public void setAttrs(XMLAttributes attrs) 553 { 554 this.attrs = attrs; 555 } 556 557 public int getLength() 558 { 559 return attrs.getLength(); 560 } 561 562 public String getLocalName(int index) 563 { 564 return attrs.getLocalName(index); 565 } 566 567 public String getQName(int index) 568 { 569 return attrs.getQName(index); 570 } 571 572 public String getType(int index) 573 { 574 return attrs.getType(index); 575 } 576 577 public String getURI(int index) 578 { 579 return attrs.getURI(index); 580 } 581 582 public String getValue(int index) 583 { 584 return attrs.getValue(index); 585 } 586 587 public int getIndex(String qName) 588 { 589 return attrs.getIndex(qName); 590 } 591 592 public String getType(String qName) 593 { 594 return attrs.getType(qName); 595 } 596 597 public String getValue(String qName) 598 { 599 return attrs.getValue(qName); 600 } 601 602 public int getIndex(String uri, String localName) 603 { 604 return attrs.getIndex(uri, localName); 605 } 606 607 public String getType(String uri, String localName) 608 { 609 return attrs.getType(uri, localName); 610 } 611 612 public String getValue(String uri, String localName) 613 { 614 return attrs.getValue(uri, localName); 615 } 616 617 public String toString() 618 { 619 StringBuffer buffer = new StringBuffer (); 620 buffer.append('('); 621 for (int i = 0; i < getLength(); ++i) 622 { 623 buffer.append(getLocalName(i)); 624 buffer.append('='); 625 buffer.append(getValue(i)); 626 if (i < getLength()-1) 627 buffer.append(", "); 628 } 629 buffer.append(')'); 630 return buffer.toString(); 631 } 632 } 633 } 634 | Popular Tags |