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