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