1 // XMLFilterImpl.java - base SAX2 filter implementation. 2 // http://www.saxproject.org 3 // Written by David Megginson 4 // NO WARRANTY! This class is in the Public Domain. 5 // $Id: XMLFilterImpl.java,v 1.9 2004/04/26 17:34:35 dmegginson Exp $ 6 7 package org.xml.sax.helpers; 8 9 import java.io.IOException; 10 import org.xml.sax.Attributes; 11 import org.xml.sax.ContentHandler; 12 import org.xml.sax.DTDHandler; 13 import org.xml.sax.EntityResolver; 14 import org.xml.sax.ErrorHandler; 15 import org.xml.sax.InputSource; 16 import org.xml.sax.Locator; 17 import org.xml.sax.SAXException; 18 import org.xml.sax.SAXNotRecognizedException; 19 import org.xml.sax.SAXNotSupportedException; 20 import org.xml.sax.SAXParseException; 21 import org.xml.sax.XMLFilter; 22 import org.xml.sax.XMLReader; 23 24 25 /** 26 * Base class for deriving an XML filter. 27 * 28 * <blockquote> 29 * <em>This module, both source code and documentation, is in the 30 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em> 31 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a> 32 * for further information. 33 * </blockquote> 34 * 35 * <p>This class is designed to sit between an {@link org.xml.sax.XMLReader 36 * XMLReader} and the client application's event handlers. By default, it 37 * does nothing but pass requests up to the reader and events 38 * on to the handlers unmodified, but subclasses can override 39 * specific methods to modify the event stream or the configuration 40 * requests as they pass through.</p> 41 * 42 * @since SAX 2.0 43 * @author David Megginson 44 * @version 2.0.1 (sax2r2) 45 * @see org.xml.sax.XMLFilter 46 * @see org.xml.sax.XMLReader 47 * @see org.xml.sax.EntityResolver 48 * @see org.xml.sax.DTDHandler 49 * @see org.xml.sax.ContentHandler 50 * @see org.xml.sax.ErrorHandler 51 */ 52 public class XMLFilterImpl 53 implements XMLFilter, EntityResolver, DTDHandler, ContentHandler, ErrorHandler 54 { 55 56 57 //////////////////////////////////////////////////////////////////// 58 // Constructors. 59 //////////////////////////////////////////////////////////////////// 60 61 62 /** 63 * Construct an empty XML filter, with no parent. 64 * 65 * <p>This filter will have no parent: you must assign a parent 66 * before you start a parse or do any configuration with 67 * setFeature or setProperty, unless you use this as a pure event 68 * consumer rather than as an {@link XMLReader}.</p> 69 * 70 * @see org.xml.sax.XMLReader#setFeature 71 * @see org.xml.sax.XMLReader#setProperty 72 * @see #setParent 73 */ XMLFilterImpl()74 public XMLFilterImpl () 75 { 76 } 77 78 79 /** 80 * Construct an XML filter with the specified parent. 81 * 82 * @param parent the XML reader from which this filter receives its events. 83 * 84 * @see #setParent 85 * @see #getParent 86 */ XMLFilterImpl(XMLReader parent)87 public XMLFilterImpl (XMLReader parent) 88 { 89 setParent(parent); 90 } 91 92 93 94 //////////////////////////////////////////////////////////////////// 95 // Implementation of org.xml.sax.XMLFilter. 96 //////////////////////////////////////////////////////////////////// 97 98 99 /** 100 * Set the parent reader. 101 * 102 * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which 103 * this filter will obtain its events and to which it will pass its 104 * configuration requests. The parent may itself be another filter.</p> 105 * 106 * <p>If there is no parent reader set, any attempt to parse 107 * or to set or get a feature or property will fail.</p> 108 * 109 * @param parent The parent XML reader. 110 * @see #getParent 111 */ setParent(XMLReader parent)112 public void setParent (XMLReader parent) 113 { 114 this.parent = parent; 115 } 116 117 118 /** 119 * Get the parent reader. 120 * 121 * @return The parent XML reader, or null if none is set. 122 * @see #setParent 123 */ getParent()124 public XMLReader getParent () 125 { 126 return parent; 127 } 128 129 130 131 //////////////////////////////////////////////////////////////////// 132 // Implementation of org.xml.sax.XMLReader. 133 //////////////////////////////////////////////////////////////////// 134 135 136 /** 137 * Set the value of a feature. 138 * 139 * <p>This will always fail if the parent is null.</p> 140 * 141 * @param name The feature name. 142 * @param value The requested feature value. 143 * @exception org.xml.sax.SAXNotRecognizedException If the feature 144 * value can't be assigned or retrieved from the parent. 145 * @exception org.xml.sax.SAXNotSupportedException When the 146 * parent recognizes the feature name but 147 * cannot set the requested value. 148 */ setFeature(String name, boolean value)149 public void setFeature (String name, boolean value) 150 throws SAXNotRecognizedException, SAXNotSupportedException 151 { 152 if (parent != null) { 153 parent.setFeature(name, value); 154 } else { 155 throw new SAXNotRecognizedException("Feature: " + name); 156 } 157 } 158 159 160 /** 161 * Look up the value of a feature. 162 * 163 * <p>This will always fail if the parent is null.</p> 164 * 165 * @param name The feature name. 166 * @return The current value of the feature. 167 * @exception org.xml.sax.SAXNotRecognizedException If the feature 168 * value can't be assigned or retrieved from the parent. 169 * @exception org.xml.sax.SAXNotSupportedException When the 170 * parent recognizes the feature name but 171 * cannot determine its value at this time. 172 */ getFeature(String name)173 public boolean getFeature (String name) 174 throws SAXNotRecognizedException, SAXNotSupportedException 175 { 176 if (parent != null) { 177 return parent.getFeature(name); 178 } else { 179 throw new SAXNotRecognizedException("Feature: " + name); 180 } 181 } 182 183 184 /** 185 * Set the value of a property. 186 * 187 * <p>This will always fail if the parent is null.</p> 188 * 189 * @param name The property name. 190 * @param value The requested property value. 191 * @exception org.xml.sax.SAXNotRecognizedException If the property 192 * value can't be assigned or retrieved from the parent. 193 * @exception org.xml.sax.SAXNotSupportedException When the 194 * parent recognizes the property name but 195 * cannot set the requested value. 196 */ setProperty(String name, Object value)197 public void setProperty (String name, Object value) 198 throws SAXNotRecognizedException, SAXNotSupportedException 199 { 200 if (parent != null) { 201 parent.setProperty(name, value); 202 } else { 203 throw new SAXNotRecognizedException("Property: " + name); 204 } 205 } 206 207 208 /** 209 * Look up the value of a property. 210 * 211 * @param name The property name. 212 * @return The current value of the property. 213 * @exception org.xml.sax.SAXNotRecognizedException If the property 214 * value can't be assigned or retrieved from the parent. 215 * @exception org.xml.sax.SAXNotSupportedException When the 216 * parent recognizes the property name but 217 * cannot determine its value at this time. 218 */ getProperty(String name)219 public Object getProperty (String name) 220 throws SAXNotRecognizedException, SAXNotSupportedException 221 { 222 if (parent != null) { 223 return parent.getProperty(name); 224 } else { 225 throw new SAXNotRecognizedException("Property: " + name); 226 } 227 } 228 229 230 /** 231 * Set the entity resolver. 232 * 233 * @param resolver The new entity resolver. 234 */ setEntityResolver(EntityResolver resolver)235 public void setEntityResolver (EntityResolver resolver) 236 { 237 entityResolver = resolver; 238 } 239 240 241 /** 242 * Get the current entity resolver. 243 * 244 * @return The current entity resolver, or null if none was set. 245 */ getEntityResolver()246 public EntityResolver getEntityResolver () 247 { 248 return entityResolver; 249 } 250 251 252 /** 253 * Set the DTD event handler. 254 * 255 * @param handler the new DTD handler 256 */ setDTDHandler(DTDHandler handler)257 public void setDTDHandler (DTDHandler handler) 258 { 259 dtdHandler = handler; 260 } 261 262 263 /** 264 * Get the current DTD event handler. 265 * 266 * @return The current DTD handler, or null if none was set. 267 */ getDTDHandler()268 public DTDHandler getDTDHandler () 269 { 270 return dtdHandler; 271 } 272 273 274 /** 275 * Set the content event handler. 276 * 277 * @param handler the new content handler 278 */ setContentHandler(ContentHandler handler)279 public void setContentHandler (ContentHandler handler) 280 { 281 contentHandler = handler; 282 } 283 284 285 /** 286 * Get the content event handler. 287 * 288 * @return The current content handler, or null if none was set. 289 */ getContentHandler()290 public ContentHandler getContentHandler () 291 { 292 return contentHandler; 293 } 294 295 296 /** 297 * Set the error event handler. 298 * 299 * @param handler the new error handler 300 */ setErrorHandler(ErrorHandler handler)301 public void setErrorHandler (ErrorHandler handler) 302 { 303 errorHandler = handler; 304 } 305 306 307 /** 308 * Get the current error event handler. 309 * 310 * @return The current error handler, or null if none was set. 311 */ getErrorHandler()312 public ErrorHandler getErrorHandler () 313 { 314 return errorHandler; 315 } 316 317 318 /** 319 * Parse a document. 320 * 321 * @param input The input source for the document entity. 322 * @exception org.xml.sax.SAXException Any SAX exception, possibly 323 * wrapping another exception. 324 * @exception java.io.IOException An IO exception from the parser, 325 * possibly from a byte stream or character stream 326 * supplied by the application. 327 */ parse(InputSource input)328 public void parse (InputSource input) 329 throws SAXException, IOException 330 { 331 setupParse(); 332 parent.parse(input); 333 } 334 335 336 /** 337 * Parse a document. 338 * 339 * @param systemId The system identifier as a fully-qualified URI. 340 * @exception org.xml.sax.SAXException Any SAX exception, possibly 341 * wrapping another exception. 342 * @exception java.io.IOException An IO exception from the parser, 343 * possibly from a byte stream or character stream 344 * supplied by the application. 345 */ parse(String systemId)346 public void parse (String systemId) 347 throws SAXException, IOException 348 { 349 parse(new InputSource(systemId)); 350 } 351 352 353 354 //////////////////////////////////////////////////////////////////// 355 // Implementation of org.xml.sax.EntityResolver. 356 //////////////////////////////////////////////////////////////////// 357 358 359 /** 360 * Filter an external entity resolution. 361 * 362 * @param publicId The entity's public identifier, or null. 363 * @param systemId The entity's system identifier. 364 * @return A new InputSource or null for the default. 365 * @exception org.xml.sax.SAXException The client may throw 366 * an exception during processing. 367 * @exception java.io.IOException The client may throw an 368 * I/O-related exception while obtaining the 369 * new InputSource. 370 */ resolveEntity(String publicId, String systemId)371 public InputSource resolveEntity (String publicId, String systemId) 372 throws SAXException, IOException 373 { 374 if (entityResolver != null) { 375 return entityResolver.resolveEntity(publicId, systemId); 376 } else { 377 return null; 378 } 379 } 380 381 382 383 //////////////////////////////////////////////////////////////////// 384 // Implementation of org.xml.sax.DTDHandler. 385 //////////////////////////////////////////////////////////////////// 386 387 388 /** 389 * Filter a notation declaration event. 390 * 391 * @param name The notation name. 392 * @param publicId The notation's public identifier, or null. 393 * @param systemId The notation's system identifier, or null. 394 * @exception org.xml.sax.SAXException The client may throw 395 * an exception during processing. 396 */ notationDecl(String name, String publicId, String systemId)397 public void notationDecl (String name, String publicId, String systemId) 398 throws SAXException 399 { 400 if (dtdHandler != null) { 401 dtdHandler.notationDecl(name, publicId, systemId); 402 } 403 } 404 405 406 /** 407 * Filter an unparsed entity declaration event. 408 * 409 * @param name The entity name. 410 * @param publicId The entity's public identifier, or null. 411 * @param systemId The entity's system identifier, or null. 412 * @param notationName The name of the associated notation. 413 * @exception org.xml.sax.SAXException The client may throw 414 * an exception during processing. 415 */ unparsedEntityDecl(String name, String publicId, String systemId, String notationName)416 public void unparsedEntityDecl (String name, String publicId, 417 String systemId, String notationName) 418 throws SAXException 419 { 420 if (dtdHandler != null) { 421 dtdHandler.unparsedEntityDecl(name, publicId, systemId, 422 notationName); 423 } 424 } 425 426 427 428 //////////////////////////////////////////////////////////////////// 429 // Implementation of org.xml.sax.ContentHandler. 430 //////////////////////////////////////////////////////////////////// 431 432 433 /** 434 * Filter a new document locator event. 435 * 436 * @param locator The document locator. 437 */ setDocumentLocator(Locator locator)438 public void setDocumentLocator (Locator locator) 439 { 440 this.locator = locator; 441 if (contentHandler != null) { 442 contentHandler.setDocumentLocator(locator); 443 } 444 } 445 446 447 /** 448 * Filter a start document event. 449 * 450 * @exception org.xml.sax.SAXException The client may throw 451 * an exception during processing. 452 */ startDocument()453 public void startDocument () 454 throws SAXException 455 { 456 if (contentHandler != null) { 457 contentHandler.startDocument(); 458 } 459 } 460 461 462 /** 463 * Filter an end document event. 464 * 465 * @exception org.xml.sax.SAXException The client may throw 466 * an exception during processing. 467 */ endDocument()468 public void endDocument () 469 throws SAXException 470 { 471 if (contentHandler != null) { 472 contentHandler.endDocument(); 473 } 474 } 475 476 477 /** 478 * Filter a start Namespace prefix mapping event. 479 * 480 * @param prefix The Namespace prefix. 481 * @param uri The Namespace URI. 482 * @exception org.xml.sax.SAXException The client may throw 483 * an exception during processing. 484 */ startPrefixMapping(String prefix, String uri)485 public void startPrefixMapping (String prefix, String uri) 486 throws SAXException 487 { 488 if (contentHandler != null) { 489 contentHandler.startPrefixMapping(prefix, uri); 490 } 491 } 492 493 494 /** 495 * Filter an end Namespace prefix mapping event. 496 * 497 * @param prefix The Namespace prefix. 498 * @exception org.xml.sax.SAXException The client may throw 499 * an exception during processing. 500 */ endPrefixMapping(String prefix)501 public void endPrefixMapping (String prefix) 502 throws SAXException 503 { 504 if (contentHandler != null) { 505 contentHandler.endPrefixMapping(prefix); 506 } 507 } 508 509 510 /** 511 * Filter a start element event. 512 * 513 * @param uri The element's Namespace URI, or the empty string. 514 * @param localName The element's local name, or the empty string. 515 * @param qName The element's qualified (prefixed) name, or the empty 516 * string. 517 * @param atts The element's attributes. 518 * @exception org.xml.sax.SAXException The client may throw 519 * an exception during processing. 520 */ startElement(String uri, String localName, String qName, Attributes atts)521 public void startElement (String uri, String localName, String qName, 522 Attributes atts) 523 throws SAXException 524 { 525 if (contentHandler != null) { 526 contentHandler.startElement(uri, localName, qName, atts); 527 } 528 } 529 530 531 /** 532 * Filter an end element event. 533 * 534 * @param uri The element's Namespace URI, or the empty string. 535 * @param localName The element's local name, or the empty string. 536 * @param qName The element's qualified (prefixed) name, or the empty 537 * string. 538 * @exception org.xml.sax.SAXException The client may throw 539 * an exception during processing. 540 */ endElement(String uri, String localName, String qName)541 public void endElement (String uri, String localName, String qName) 542 throws SAXException 543 { 544 if (contentHandler != null) { 545 contentHandler.endElement(uri, localName, qName); 546 } 547 } 548 549 550 /** 551 * Filter a character data event. 552 * 553 * @param ch An array of characters. 554 * @param start The starting position in the array. 555 * @param length The number of characters to use from the array. 556 * @exception org.xml.sax.SAXException The client may throw 557 * an exception during processing. 558 */ characters(char ch[], int start, int length)559 public void characters (char ch[], int start, int length) 560 throws SAXException 561 { 562 if (contentHandler != null) { 563 contentHandler.characters(ch, start, length); 564 } 565 } 566 567 568 /** 569 * Filter an ignorable whitespace event. 570 * 571 * @param ch An array of characters. 572 * @param start The starting position in the array. 573 * @param length The number of characters to use from the array. 574 * @exception org.xml.sax.SAXException The client may throw 575 * an exception during processing. 576 */ ignorableWhitespace(char ch[], int start, int length)577 public void ignorableWhitespace (char ch[], int start, int length) 578 throws SAXException 579 { 580 if (contentHandler != null) { 581 contentHandler.ignorableWhitespace(ch, start, length); 582 } 583 } 584 585 586 /** 587 * Filter a processing instruction event. 588 * 589 * @param target The processing instruction target. 590 * @param data The text following the target. 591 * @exception org.xml.sax.SAXException The client may throw 592 * an exception during processing. 593 */ processingInstruction(String target, String data)594 public void processingInstruction (String target, String data) 595 throws SAXException 596 { 597 if (contentHandler != null) { 598 contentHandler.processingInstruction(target, data); 599 } 600 } 601 602 603 /** 604 * Filter a skipped entity event. 605 * 606 * @param name The name of the skipped entity. 607 * @exception org.xml.sax.SAXException The client may throw 608 * an exception during processing. 609 */ skippedEntity(String name)610 public void skippedEntity (String name) 611 throws SAXException 612 { 613 if (contentHandler != null) { 614 contentHandler.skippedEntity(name); 615 } 616 } 617 618 619 620 //////////////////////////////////////////////////////////////////// 621 // Implementation of org.xml.sax.ErrorHandler. 622 //////////////////////////////////////////////////////////////////// 623 624 625 /** 626 * Filter a warning event. 627 * 628 * @param e The warning as an exception. 629 * @exception org.xml.sax.SAXException The client may throw 630 * an exception during processing. 631 */ warning(SAXParseException e)632 public void warning (SAXParseException e) 633 throws SAXException 634 { 635 if (errorHandler != null) { 636 errorHandler.warning(e); 637 } 638 } 639 640 641 /** 642 * Filter an error event. 643 * 644 * @param e The error as an exception. 645 * @exception org.xml.sax.SAXException The client may throw 646 * an exception during processing. 647 */ error(SAXParseException e)648 public void error (SAXParseException e) 649 throws SAXException 650 { 651 if (errorHandler != null) { 652 errorHandler.error(e); 653 } 654 } 655 656 657 /** 658 * Filter a fatal error event. 659 * 660 * @param e The error as an exception. 661 * @exception org.xml.sax.SAXException The client may throw 662 * an exception during processing. 663 */ fatalError(SAXParseException e)664 public void fatalError (SAXParseException e) 665 throws SAXException 666 { 667 if (errorHandler != null) { 668 errorHandler.fatalError(e); 669 } 670 } 671 672 673 674 //////////////////////////////////////////////////////////////////// 675 // Internal methods. 676 //////////////////////////////////////////////////////////////////// 677 678 679 /** 680 * Set up before a parse. 681 * 682 * <p>Before every parse, check whether the parent is 683 * non-null, and re-register the filter for all of the 684 * events.</p> 685 */ setupParse()686 private void setupParse () 687 { 688 if (parent == null) { 689 throw new NullPointerException("No parent for filter"); 690 } 691 parent.setEntityResolver(this); 692 parent.setDTDHandler(this); 693 parent.setContentHandler(this); 694 parent.setErrorHandler(this); 695 } 696 697 698 699 //////////////////////////////////////////////////////////////////// 700 // Internal state. 701 //////////////////////////////////////////////////////////////////// 702 703 private XMLReader parent = null; 704 private Locator locator = null; 705 private EntityResolver entityResolver = null; 706 private DTDHandler dtdHandler = null; 707 private ContentHandler contentHandler = null; 708 private ErrorHandler errorHandler = null; 709 710 } 711 712 // end of XMLFilterImpl.java 713