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