Source for org.xml.sax.helpers.XMLReaderAdapter

   1: // XMLReaderAdapter.java - adapt an SAX2 XMLReader to a SAX1 Parser
   2: // http://www.saxproject.org
   3: // Written by David Megginson
   4: // NO WARRANTY!  This class is in the public domain.
   5: // $Id: XMLReaderAdapter.java,v 1.2 2006/12/10 20:25:41 gnu_andrew Exp $
   6: 
   7: package org.xml.sax.helpers;
   8: 
   9: import java.io.IOException;
  10: import java.util.Locale;
  11: 
  12: import org.xml.sax.Parser;    // deprecated
  13: import org.xml.sax.Locator;
  14: import org.xml.sax.InputSource;
  15: import org.xml.sax.AttributeList; // deprecated
  16: import org.xml.sax.EntityResolver;
  17: import org.xml.sax.DTDHandler;
  18: import org.xml.sax.DocumentHandler; // deprecated
  19: import org.xml.sax.ErrorHandler;
  20: import org.xml.sax.SAXException;
  21: 
  22: import org.xml.sax.XMLReader;
  23: import org.xml.sax.Attributes;
  24: import org.xml.sax.ContentHandler;
  25: import org.xml.sax.SAXNotSupportedException;
  26: 
  27: 
  28: /**
  29:  * Adapt a SAX2 XMLReader as a SAX1 Parser.
  30:  *
  31:  * <blockquote>
  32:  * <em>This module, both source code and documentation, is in the
  33:  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
  34:  * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
  35:  * for further information.
  36:  * </blockquote>
  37:  *
  38:  * <p>This class wraps a SAX2 {@link org.xml.sax.XMLReader XMLReader}
  39:  * and makes it act as a SAX1 {@link org.xml.sax.Parser Parser}.  The XMLReader 
  40:  * must support a true value for the 
  41:  * http://xml.org/sax/features/namespace-prefixes property or parsing will fail
  42:  * with a {@link org.xml.sax.SAXException SAXException}; if the XMLReader 
  43:  * supports a false value for the http://xml.org/sax/features/namespaces 
  44:  * property, that will also be used to improve efficiency.</p>
  45:  *
  46:  * @since SAX 2.0
  47:  * @author David Megginson
  48:  * @version 2.0.1 (sax2r2)
  49:  * @see org.xml.sax.Parser
  50:  * @see org.xml.sax.XMLReader
  51:  */
  52: public class XMLReaderAdapter implements Parser, ContentHandler
  53: {
  54: 
  55: 
  56:     ////////////////////////////////////////////////////////////////////
  57:     // Constructor.
  58:     ////////////////////////////////////////////////////////////////////
  59: 
  60: 
  61:     /**
  62:      * Create a new adapter.
  63:      *
  64:      * <p>Use the "org.xml.sax.driver" property to locate the SAX2
  65:      * driver to embed.</p>
  66:      *
  67:      * @exception org.xml.sax.SAXException If the embedded driver
  68:      *            cannot be instantiated or if the
  69:      *            org.xml.sax.driver property is not specified.
  70:      */
  71:     public XMLReaderAdapter ()
  72:       throws SAXException
  73:     {
  74:     setup(XMLReaderFactory.createXMLReader());
  75:     }
  76: 
  77: 
  78:     /**
  79:      * Create a new adapter.
  80:      *
  81:      * <p>Create a new adapter, wrapped around a SAX2 XMLReader.
  82:      * The adapter will make the XMLReader act like a SAX1
  83:      * Parser.</p>
  84:      *
  85:      * @param xmlReader The SAX2 XMLReader to wrap.
  86:      * @exception java.lang.NullPointerException If the argument is null.
  87:      */
  88:     public XMLReaderAdapter (XMLReader xmlReader)
  89:     {
  90:     setup(xmlReader);
  91:     }
  92: 
  93: 
  94: 
  95:     /**
  96:      * Internal setup.
  97:      *
  98:      * @param xmlReader The embedded XMLReader.
  99:      */
 100:     private void setup (XMLReader xmlReader)
 101:     {
 102:     if (xmlReader == null) {
 103:         throw new NullPointerException("XMLReader must not be null");
 104:     }
 105:     this.xmlReader = xmlReader;
 106:     qAtts = new AttributesAdapter();
 107:     }
 108: 
 109: 
 110: 
 111:     ////////////////////////////////////////////////////////////////////
 112:     // Implementation of org.xml.sax.Parser.
 113:     ////////////////////////////////////////////////////////////////////
 114: 
 115: 
 116:     /**
 117:      * Set the locale for error reporting.
 118:      *
 119:      * <p>This is not supported in SAX2, and will always throw
 120:      * an exception.</p>
 121:      *
 122:      * @param locale the locale for error reporting.
 123:      * @see org.xml.sax.Parser#setLocale
 124:      * @exception org.xml.sax.SAXException Thrown unless overridden.
 125:      */
 126:     public void setLocale (Locale locale)
 127:     throws SAXException
 128:     {
 129:     throw new SAXNotSupportedException("setLocale not supported");
 130:     }
 131: 
 132: 
 133:     /**
 134:      * Register the entity resolver.
 135:      *
 136:      * @param resolver The new resolver.
 137:      * @see org.xml.sax.Parser#setEntityResolver
 138:      */
 139:     public void setEntityResolver (EntityResolver resolver)
 140:     {
 141:     xmlReader.setEntityResolver(resolver);
 142:     }
 143: 
 144: 
 145:     /**
 146:      * Register the DTD event handler.
 147:      *
 148:      * @param handler The new DTD event handler.
 149:      * @see org.xml.sax.Parser#setDTDHandler
 150:      */
 151:     public void setDTDHandler (DTDHandler handler)
 152:     {
 153:     xmlReader.setDTDHandler(handler);
 154:     }
 155: 
 156: 
 157:     /**
 158:      * Register the SAX1 document event handler.
 159:      *
 160:      * <p>Note that the SAX1 document handler has no Namespace
 161:      * support.</p>
 162:      *
 163:      * @param handler The new SAX1 document event handler.
 164:      * @see org.xml.sax.Parser#setDocumentHandler
 165:      */
 166:     public void setDocumentHandler (DocumentHandler handler)
 167:     {
 168:     documentHandler = handler;
 169:     }
 170: 
 171: 
 172:     /**
 173:      * Register the error event handler.
 174:      *
 175:      * @param handler The new error event handler.
 176:      * @see org.xml.sax.Parser#setErrorHandler
 177:      */
 178:     public void setErrorHandler (ErrorHandler handler)
 179:     {
 180:     xmlReader.setErrorHandler(handler);
 181:     }
 182: 
 183: 
 184:     /**
 185:      * Parse the document.
 186:      *
 187:      * <p>This method will throw an exception if the embedded
 188:      * XMLReader does not support the 
 189:      * http://xml.org/sax/features/namespace-prefixes property.</p>
 190:      *
 191:      * @param systemId The absolute URL of the document.
 192:      * @exception java.io.IOException If there is a problem reading
 193:      *            the raw content of the document.
 194:      * @exception org.xml.sax.SAXException If there is a problem
 195:      *            processing the document.
 196:      * @see #parse(org.xml.sax.InputSource)
 197:      * @see org.xml.sax.Parser#parse(java.lang.String)
 198:      */
 199:     public void parse (String systemId)
 200:     throws IOException, SAXException
 201:     {
 202:     parse(new InputSource(systemId));
 203:     }
 204: 
 205: 
 206:     /**
 207:      * Parse the document.
 208:      *
 209:      * <p>This method will throw an exception if the embedded
 210:      * XMLReader does not support the 
 211:      * http://xml.org/sax/features/namespace-prefixes property.</p>
 212:      *
 213:      * @param input An input source for the document.
 214:      * @exception java.io.IOException If there is a problem reading
 215:      *            the raw content of the document.
 216:      * @exception org.xml.sax.SAXException If there is a problem
 217:      *            processing the document.
 218:      * @see #parse(java.lang.String)
 219:      * @see org.xml.sax.Parser#parse(org.xml.sax.InputSource)
 220:      */
 221:     public void parse (InputSource input)
 222:     throws IOException, SAXException
 223:     {
 224:     setupXMLReader();
 225:     xmlReader.parse(input);
 226:     }
 227: 
 228: 
 229:     /**
 230:      * Set up the XML reader.
 231:      */
 232:     private void setupXMLReader ()
 233:     throws SAXException
 234:     {
 235:     xmlReader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
 236:     try {
 237:         xmlReader.setFeature("http://xml.org/sax/features/namespaces",
 238:                              false);
 239:     } catch (SAXException e) {
 240:         // NO OP: it's just extra information, and we can ignore it
 241:     }
 242:     xmlReader.setContentHandler(this);
 243:     }
 244: 
 245: 
 246: 
 247:     ////////////////////////////////////////////////////////////////////
 248:     // Implementation of org.xml.sax.ContentHandler.
 249:     ////////////////////////////////////////////////////////////////////
 250: 
 251: 
 252:     /**
 253:      * Set a document locator.
 254:      *
 255:      * @param locator The document locator.
 256:      * @see org.xml.sax.ContentHandler#setDocumentLocator
 257:      */
 258:     public void setDocumentLocator (Locator locator)
 259:     {
 260:     if (documentHandler != null)
 261:         documentHandler.setDocumentLocator(locator);
 262:     }
 263: 
 264: 
 265:     /**
 266:      * Start document event.
 267:      *
 268:      * @exception org.xml.sax.SAXException The client may raise a
 269:      *            processing exception.
 270:      * @see org.xml.sax.ContentHandler#startDocument
 271:      */
 272:     public void startDocument ()
 273:     throws SAXException
 274:     {
 275:     if (documentHandler != null)
 276:         documentHandler.startDocument();
 277:     }
 278: 
 279: 
 280:     /**
 281:      * End document event.
 282:      *
 283:      * @exception org.xml.sax.SAXException The client may raise a
 284:      *            processing exception.
 285:      * @see org.xml.sax.ContentHandler#endDocument
 286:      */
 287:     public void endDocument ()
 288:     throws SAXException
 289:     {
 290:     if (documentHandler != null)
 291:         documentHandler.endDocument();
 292:     }
 293: 
 294: 
 295:     /**
 296:      * Adapt a SAX2 start prefix mapping event.
 297:      *
 298:      * @param prefix The prefix being mapped.
 299:      * @param uri The Namespace URI being mapped to.
 300:      * @see org.xml.sax.ContentHandler#startPrefixMapping
 301:      */
 302:     public void startPrefixMapping (String prefix, String uri)
 303:     {
 304:     }
 305: 
 306: 
 307:     /**
 308:      * Adapt a SAX2 end prefix mapping event.
 309:      *
 310:      * @param prefix The prefix being mapped.
 311:      * @see org.xml.sax.ContentHandler#endPrefixMapping
 312:      */
 313:     public void endPrefixMapping (String prefix)
 314:     {
 315:     }
 316: 
 317: 
 318:     /**
 319:      * Adapt a SAX2 start element event.
 320:      *
 321:      * @param uri The Namespace URI.
 322:      * @param localName The Namespace local name.
 323:      * @param qName The qualified (prefixed) name.
 324:      * @param atts The SAX2 attributes.
 325:      * @exception org.xml.sax.SAXException The client may raise a
 326:      *            processing exception.
 327:      * @see org.xml.sax.ContentHandler#endDocument
 328:      */
 329:     public void startElement (String uri, String localName,
 330:                   String qName, Attributes atts)
 331:     throws SAXException
 332:     {
 333:     if (documentHandler != null) {
 334:         qAtts.setAttributes(atts);
 335:         documentHandler.startElement(qName, qAtts);
 336:     }
 337:     }
 338: 
 339: 
 340:     /**
 341:      * Adapt a SAX2 end element event.
 342:      *
 343:      * @param uri The Namespace URI.
 344:      * @param localName The Namespace local name.
 345:      * @param qName The qualified (prefixed) name.
 346:      * @exception org.xml.sax.SAXException The client may raise a
 347:      *            processing exception.
 348:      * @see org.xml.sax.ContentHandler#endElement
 349:      */
 350:     public void endElement (String uri, String localName,
 351:                 String qName)
 352:     throws SAXException
 353:     {
 354:     if (documentHandler != null)
 355:         documentHandler.endElement(qName);
 356:     }
 357: 
 358: 
 359:     /**
 360:      * Adapt a SAX2 characters event.
 361:      *
 362:      * @param ch An array of characters.
 363:      * @param start The starting position in the array.
 364:      * @param length The number of characters to use.
 365:      * @exception org.xml.sax.SAXException The client may raise a
 366:      *            processing exception.
 367:      * @see org.xml.sax.ContentHandler#characters
 368:      */
 369:     public void characters (char ch[], int start, int length)
 370:     throws SAXException
 371:     {
 372:     if (documentHandler != null)
 373:         documentHandler.characters(ch, start, length);
 374:     }
 375: 
 376: 
 377:     /**
 378:      * Adapt a SAX2 ignorable whitespace event.
 379:      *
 380:      * @param ch An array of characters.
 381:      * @param start The starting position in the array.
 382:      * @param length The number of characters to use.
 383:      * @exception org.xml.sax.SAXException The client may raise a
 384:      *            processing exception.
 385:      * @see org.xml.sax.ContentHandler#ignorableWhitespace
 386:      */
 387:     public void ignorableWhitespace (char ch[], int start, int length)
 388:     throws SAXException
 389:     {
 390:     if (documentHandler != null)
 391:         documentHandler.ignorableWhitespace(ch, start, length);
 392:     }
 393: 
 394: 
 395:     /**
 396:      * Adapt a SAX2 processing instruction event.
 397:      *
 398:      * @param target The processing instruction target.
 399:      * @param data The remainder of the processing instruction
 400:      * @exception org.xml.sax.SAXException The client may raise a
 401:      *            processing exception.
 402:      * @see org.xml.sax.ContentHandler#processingInstruction
 403:      */
 404:     public void processingInstruction (String target, String data)
 405:     throws SAXException
 406:     {
 407:     if (documentHandler != null)
 408:         documentHandler.processingInstruction(target, data);
 409:     }
 410: 
 411: 
 412:     /**
 413:      * Adapt a SAX2 skipped entity event.
 414:      *
 415:      * @param name The name of the skipped entity.
 416:      * @see org.xml.sax.ContentHandler#skippedEntity
 417:      * @exception org.xml.sax.SAXException Throwable by subclasses.
 418:      */
 419:     public void skippedEntity (String name)
 420:     throws SAXException
 421:     {
 422:     }
 423: 
 424: 
 425: 
 426:     ////////////////////////////////////////////////////////////////////
 427:     // Internal state.
 428:     ////////////////////////////////////////////////////////////////////
 429: 
 430:     XMLReader xmlReader;
 431:     DocumentHandler documentHandler;
 432:     AttributesAdapter qAtts;
 433: 
 434: 
 435: 
 436:     ////////////////////////////////////////////////////////////////////
 437:     // Internal class.
 438:     ////////////////////////////////////////////////////////////////////
 439: 
 440: 
 441:     /**
 442:      * Internal class to wrap a SAX2 Attributes object for SAX1.
 443:      */
 444:     final class AttributesAdapter implements AttributeList
 445:     {
 446:     AttributesAdapter ()
 447:     {
 448:     }
 449: 
 450: 
 451:     /**
 452:      * Set the embedded Attributes object.
 453:      *
 454:      * @param The embedded SAX2 Attributes.
 455:      */ 
 456:     void setAttributes (Attributes attributes)
 457:     {
 458:         this.attributes = attributes;
 459:     }
 460: 
 461: 
 462:     /**
 463:      * Return the number of attributes.
 464:      *
 465:      * @return The length of the attribute list.
 466:      * @see org.xml.sax.AttributeList#getLength
 467:      */
 468:     public int getLength ()
 469:     {
 470:         return attributes.getLength();
 471:     }
 472: 
 473: 
 474:     /**
 475:      * Return the qualified (prefixed) name of an attribute by position.
 476:      *
 477:      * @return The qualified name.
 478:      * @see org.xml.sax.AttributeList#getName
 479:      */
 480:     public String getName (int i)
 481:     {
 482:         return attributes.getQName(i);
 483:     }
 484: 
 485: 
 486:     /**
 487:      * Return the type of an attribute by position.
 488:      *
 489:      * @return The type.
 490:      * @see org.xml.sax.AttributeList#getType(int)
 491:      */
 492:     public String getType (int i)
 493:     {
 494:         return attributes.getType(i);
 495:     }
 496: 
 497: 
 498:     /**
 499:      * Return the value of an attribute by position.
 500:      *
 501:      * @return The value.
 502:      * @see org.xml.sax.AttributeList#getValue(int)
 503:      */
 504:     public String getValue (int i)
 505:     {
 506:         return attributes.getValue(i);
 507:     }
 508: 
 509: 
 510:     /**
 511:      * Return the type of an attribute by qualified (prefixed) name.
 512:      *
 513:      * @return The type.
 514:      * @see org.xml.sax.AttributeList#getType(java.lang.String)
 515:      */
 516:     public String getType (String qName)
 517:     {
 518:         return attributes.getType(qName);
 519:     }
 520: 
 521: 
 522:     /**
 523:      * Return the value of an attribute by qualified (prefixed) name.
 524:      *
 525:      * @return The value.
 526:      * @see org.xml.sax.AttributeList#getValue(java.lang.String)
 527:      */
 528:     public String getValue (String qName)
 529:     {
 530:         return attributes.getValue(qName);
 531:     }
 532: 
 533:     private Attributes attributes;
 534:     }
 535: 
 536: }
 537: 
 538: // end of XMLReaderAdapter.java