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 //////////////////////////////////////////////////////////////////// 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 } 78 79 80 /** 81 * Construct an XML filter with the specified parent. 82 * 83 * @param parent the XML reader from which this filter receives its events. 84 * 85 * @see #setParent 86 * @see #getParent 87 */ 88 public XMLFilterImpl (XMLReader parent) 89 { 90 setParent(parent); 91 } 92 93 94 95 //////////////////////////////////////////////////////////////////// 97 // Implementation of org.xml.sax.XMLFilter. 98 //////////////////////////////////////////////////////////////////// 99 100 101 /** 102 * Set the parent reader. 103 * 104 * <p>This is the {@link org.xml.sax.XMLReader XMLReader} from which 105 * this filter will obtain its events and to which it will pass its 106 * configuration requests. The parent may itself be another filter.</p> 107 * 108 * <p>If there is no parent reader set, any attempt to parse 109 * or to set or get a feature or property will fail.</p> 110 * 111 * @param parent The parent XML reader. 112 * @see #getParent 113 */ 114 public void setParent (XMLReader parent) 115 { 116 this.parent = parent; 117 } 118 119 120 /** 121 * Get the parent reader. 122 * 123 * @return The parent XML reader, or null if none is set. 124 * @see #setParent 125 */ 126 public XMLReader getParent () 127 { 128 return parent; 129 } 130 131 132 133 //////////////////////////////////////////////////////////////////// 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 //////////////////////////////////////////////////////////////////// 359 // Implementation of org.xml.sax.EntityResolver. 360 //////////////////////////////////////////////////////////////////// 361 362 363 /** 364 * Filter an external entity resolution. 365 * 366 * @param publicId The entity's public identifier, or null. 367 * @param systemId The entity's system identifier. 368 * @return A new InputSource or null for the default. 369 * @exception org.xml.sax.SAXException The client may throw 370 * an exception during processing. 371 * @exception java.io.IOException The client may throw an 372 * I/O-related exception while obtaining the 373 * new InputSource. 374 */ 375 public InputSource resolveEntity (String publicId, String systemId) 376 throws SAXException, IOException 377 { 378 if (entityResolver != null) { 379 return entityResolver.resolveEntity(publicId, systemId); 380 } else { 381 return null; 382 } 383 } 384 385 386 387 //////////////////////////////////////////////////////////////////// 389 // Implementation of org.xml.sax.DTDHandler. 390 //////////////////////////////////////////////////////////////////// 391 392 393 /** 394 * Filter a notation declaration event. 395 * 396 * @param name The notation name. 397 * @param publicId The notation's public identifier, or null. 398 * @param systemId The notation's system identifier, or null. 399 * @exception org.xml.sax.SAXException The client may throw 400 * an exception during processing. 401 */ 402 public void notationDecl (String name, String publicId, String systemId) 403 throws SAXException 404 { 405 if (dtdHandler != null) { 406 dtdHandler.notationDecl(name, publicId, systemId); 407 } 408 } 409 410 411 /** 412 * Filter an unparsed entity declaration event. 413 * 414 * @param name The entity name. 415 * @param publicId The entity's public identifier, or null. 416 * @param systemId The entity's system identifier, or null. 417 * @param notationName The name of the associated notation. 418 * @exception org.xml.sax.SAXException The client may throw 419 * an exception during processing. 420 */ 421 public void unparsedEntityDecl (String name, String publicId, 422 String systemId, String notationName) 423 throws SAXException 424 { 425 if (dtdHandler != null) { 426 dtdHandler.unparsedEntityDecl(name, publicId, systemId, 427 notationName); 428 } 429 } 430 431 432 433 //////////////////////////////////////////////////////////////////// 435 // Implementation of org.xml.sax.ContentHandler. 436 //////////////////////////////////////////////////////////////////// 437 438 439 /** 440 * Filter a new document locator event. 441 * 442 * @param locator The document locator. 443 */ 444 public void setDocumentLocator (Locator locator) 445 { 446 this.locator = locator; 447 if (contentHandler != null) { 448 contentHandler.setDocumentLocator(locator); 449 } 450 } 451 452 453 /** 454 * Filter a start document event. 455 * 456 * @exception org.xml.sax.SAXException The client may throw 457 * an exception during processing. 458 */ 459 public void startDocument () 460 throws SAXException 461 { 462 if (contentHandler != null) { 463 contentHandler.startDocument(); 464 } 465 } 466 467 468 /** 469 * Filter an end document event. 470 * 471 * @exception org.xml.sax.SAXException The client may throw 472 * an exception during processing. 473 */ 474 public void endDocument () 475 throws SAXException 476 { 477 if (contentHandler != null) { 478 contentHandler.endDocument(); 479 } 480 } 481 482 483 /** 484 * Filter a start Namespace prefix mapping event. 485 * 486 * @param prefix The Namespace prefix. 487 * @param uri The Namespace URI. 488 * @exception org.xml.sax.SAXException The client may throw 489 * an exception during processing. 490 */ 491 public void startPrefixMapping (String prefix, String uri) 492 throws SAXException 493 { 494 if (contentHandler != null) { 495 contentHandler.startPrefixMapping(prefix, uri); 496 } 497 } 498 499 500 /** 501 * Filter an end Namespace prefix mapping event. 502 * 503 * @param prefix The Namespace prefix. 504 * @exception org.xml.sax.SAXException The client may throw 505 * an exception during processing. 506 */ 507 public void endPrefixMapping (String prefix) 508 throws SAXException 509 { 510 if (contentHandler != null) { 511 contentHandler.endPrefixMapping(prefix); 512 } 513 } 514 515 516 /** 517 * Filter a start element event. 518 * 519 * @param uri The element's Namespace URI, or the empty string. 520 * @param localName The element's local name, or the empty string. 521 * @param qName The element's qualified (prefixed) name, or the empty 522 * string. 523 * @param atts The element's attributes. 524 * @exception org.xml.sax.SAXException The client may throw 525 * an exception during processing. 526 */ 527 public void startElement (String uri, String localName, String qName, 528 Attributes atts) 529 throws SAXException 530 { 531 if (contentHandler != null) { 532 contentHandler.startElement(uri, localName, qName, atts); 533 } 534 } 535 536 537 /** 538 * Filter an end element event. 539 * 540 * @param uri The element's Namespace URI, or the empty string. 541 * @param localName The element's local name, or the empty string. 542 * @param qName The element's qualified (prefixed) name, or the empty 543 * string. 544 * @exception org.xml.sax.SAXException The client may throw 545 * an exception during processing. 546 */ 547 public void endElement (String uri, String localName, String qName) 548 throws SAXException 549 { 550 if (contentHandler != null) { 551 contentHandler.endElement(uri, localName, qName); 552 } 553 } 554 555 556 /** 557 * Filter a character data event. 558 * 559 * @param ch An array of characters. 560 * @param start The starting position in the array. 561 * @param length The number of characters to use from the array. 562 * @exception org.xml.sax.SAXException The client may throw 563 * an exception during processing. 564 */ 565 public void characters (char ch[], int start, int length) 566 throws SAXException 567 { 568 if (contentHandler != null) { 569 contentHandler.characters(ch, start, length); 570 } 571 } 572 573 574 /** 575 * Filter an ignorable whitespace event. 576 * 577 * @param ch An array of characters. 578 * @param start The starting position in the array. 579 * @param length The number of characters to use from the array. 580 * @exception org.xml.sax.SAXException The client may throw 581 * an exception during processing. 582 */ 583 public void ignorableWhitespace (char ch[], int start, int length) 584 throws SAXException 585 { 586 if (contentHandler != null) { 587 contentHandler.ignorableWhitespace(ch, start, length); 588 } 589 } 590 591 592 /** 593 * Filter a processing instruction event. 594 * 595 * @param target The processing instruction target. 596 * @param data The text following the target. 597 * @exception org.xml.sax.SAXException The client may throw 598 * an exception during processing. 599 */ 600 public void processingInstruction (String target, String data) 601 throws SAXException 602 { 603 if (contentHandler != null) { 604 contentHandler.processingInstruction(target, data); 605 } 606 } 607 608 609 /** 610 * Filter a skipped entity event. 611 * 612 * @param name The name of the skipped entity. 613 * @exception org.xml.sax.SAXException The client may throw 614 * an exception during processing. 615 */ 616 public void skippedEntity (String name) 617 throws SAXException 618 { 619 if (contentHandler != null) { 620 contentHandler.skippedEntity(name); 621 } 622 } 623 624 625 626 //////////////////////////////////////////////////////////////////// 628 // Implementation of org.xml.sax.ErrorHandler. 629 //////////////////////////////////////////////////////////////////// 630 631 632 /** 633 * Filter a warning event. 634 * 635 * @param e The warning as an exception. 636 * @exception org.xml.sax.SAXException The client may throw 637 * an exception during processing. 638 */ 639 public void warning (SAXParseException e) 640 throws SAXException 641 { 642 if (errorHandler != null) { 643 errorHandler.warning(e); 644 } 645 } 646 647 648 /** 649 * Filter an error event. 650 * 651 * @param e The error as an exception. 652 * @exception org.xml.sax.SAXException The client may throw 653 * an exception during processing. 654 */ 655 public void error (SAXParseException e) 656 throws SAXException 657 { 658 if (errorHandler != null) { 659 errorHandler.error(e); 660 } 661 } 662 663 664 /** 665 * Filter a fatal error event. 666 * 667 * @param e The error as an exception. 668 * @exception org.xml.sax.SAXException The client may throw 669 * an exception during processing. 670 */ 671 public void fatalError (SAXParseException e) 672 throws SAXException 673 { 674 if (errorHandler != null) { 675 errorHandler.fatalError(e); 676 } 677 } 678 679 680 681 //////////////////////////////////////////////////////////////////// 683 // Internal methods. 684 //////////////////////////////////////////////////////////////////// 685 686 687 /** 688 * Set up before a parse. 689 * 690 * <p>Before every parse, check whether the parent is 691 * non-null, and re-register the filter for all of the 692 * events.</p> 693 */ 694 private void setupParse () 695 { 696 if (parent == null) { 697 throw new NullPointerException("No parent for filter"); 698 } 699 parent.setEntityResolver(this); 700 parent.setDTDHandler(this); 701 parent.setContentHandler(this); 702 parent.setErrorHandler(this); 703 } 704 705 706 707 //////////////////////////////////////////////////////////////////// 709 // Internal state. 710 //////////////////////////////////////////////////////////////////// 711 712 private XMLReader parent = null; 713 private Locator locator = null; 714 private EntityResolver entityResolver = null; 715 private DTDHandler dtdHandler = null; 716 private ContentHandler contentHandler = null; 717 private ErrorHandler errorHandler = null; 718 719 } 720 721 // end of XMLFilterImpl.java 722