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