Source for gnu.xml.stream.SAXParser

   1: /* SAXParser.java -- 
   2:    Copyright (C) 2005, 2006, 2007  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.xml.stream;
  39: 
  40: import java.io.InputStream;
  41: import java.io.IOException;
  42: import java.io.Reader;
  43: import java.net.URL;
  44: import java.util.Iterator;
  45: import java.util.Map;
  46: import javax.xml.XMLConstants;
  47: import javax.xml.namespace.QName;
  48: import javax.xml.stream.Location;
  49: import javax.xml.stream.XMLEventReader;
  50: import javax.xml.stream.XMLReporter;
  51: import javax.xml.stream.XMLResolver;
  52: import javax.xml.stream.XMLStreamConstants;
  53: import javax.xml.stream.XMLStreamException;
  54: import javax.xml.stream.XMLStreamReader;
  55: 
  56: import org.xml.sax.ContentHandler;
  57: import org.xml.sax.DTDHandler;
  58: import org.xml.sax.EntityResolver;
  59: import org.xml.sax.ErrorHandler;
  60: import org.xml.sax.InputSource;
  61: import org.xml.sax.Parser;
  62: import org.xml.sax.SAXException;
  63: import org.xml.sax.SAXNotRecognizedException;
  64: import org.xml.sax.SAXNotSupportedException;
  65: import org.xml.sax.SAXParseException;
  66: import org.xml.sax.XMLReader;
  67: import org.xml.sax.ext.Attributes2;
  68: import org.xml.sax.ext.DeclHandler;
  69: import org.xml.sax.ext.EntityResolver2;
  70: import org.xml.sax.ext.LexicalHandler;
  71: import org.xml.sax.ext.Locator2;
  72: 
  73: /**
  74:  * JAXP SAX parser using an underlying StAX parser.
  75:  * This parser supports the following additional SAX features and
  76:  * properties:
  77:  * <table>
  78:  * <tr><th colspan='4'>Features</th></tr>
  79:  * <tr><td>http://gnu.org/sax/features/xml-base</td>
  80:  * <td colspan='2'>read/write</td>
  81:  * <td>Indicates or sets whether XML Base processing is enabled</td></tr>
  82:  * <tr><th colspan='4'>Properties</th></tr>
  83:  * <tr><td>http://gnu.org/sax/properties/base-uri</td>
  84:  * <td>read-only</td><td>String</td>
  85:  * <td>Returns the base URI of the current event</td></tr>
  86:  * <tr><td>http://gnu.org/sax/properties/document-xml-encoding</td>
  87:  * <td>read-only</td><td>String</td>
  88:  * <td>Returns the encoding specified in the XML declaration</td></tr>
  89:  * </table>
  90:  *
  91:  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
  92:  */
  93: public class SAXParser
  94:   extends javax.xml.parsers.SAXParser
  95:   implements XMLReader, Attributes2, Locator2, XMLReporter, XMLResolver
  96: {
  97: 
  98:   ContentHandler contentHandler;
  99:   DeclHandler declHandler;
 100:   DTDHandler dtdHandler;
 101:   EntityResolver entityResolver;
 102:   ErrorHandler errorHandler;
 103:   LexicalHandler lexicalHandler;
 104: 
 105:   boolean validating = false;
 106:   boolean namespaceAware = true;
 107:   boolean xIncludeAware = false;
 108:   boolean stringInterning = true;
 109:   boolean coalescing = true;
 110:   boolean replaceERefs = true;
 111:   boolean externalEntities = true;
 112:   boolean supportDTD = true;
 113:   boolean baseAware = true;
 114: 
 115:   XMLParser parser;
 116:   XMLStreamReader reader;
 117:   String encoding;
 118:   String xmlVersion;
 119:   boolean xmlStandalone;
 120:   String xmlEncoding;
 121:   String baseURI;
 122: 
 123:   public SAXParser()
 124:   {
 125:   }
 126: 
 127:   SAXParser(boolean validating, boolean namespaceAware, boolean xIncludeAware)
 128:   {
 129:     this.validating = validating;
 130:     this.namespaceAware = namespaceAware;
 131:     this.xIncludeAware = xIncludeAware;
 132:   }
 133: 
 134:   // -- SAXParser --
 135:   
 136:   public Parser getParser()
 137:     throws SAXException
 138:   {
 139:     return null;
 140:   }
 141:   
 142:   public XMLReader getXMLReader()
 143:     throws SAXException
 144:   {
 145:     return this;
 146:   }
 147: 
 148:   public boolean isNamespaceAware()
 149:   {
 150:     return namespaceAware;
 151:   }
 152: 
 153:   public boolean isValidating()
 154:   {
 155:     return validating;
 156:   }
 157: 
 158:   public void setProperty(String name, Object value)
 159:     throws SAXNotRecognizedException, SAXNotSupportedException
 160:   {
 161:     if (parser != null)
 162:       throw new IllegalStateException("parsing in progress");
 163:     final String FEATURES = "http://xml.org/sax/features/";
 164:     final String PROPERTIES = "http://xml.org/sax/properties/";
 165:     final String GNU_FEATURES = "http://gnu.org/sax/features/";
 166:     if ((FEATURES + "namespaces").equals(name))
 167:       namespaceAware = Boolean.TRUE.equals(value);
 168:     else if ((FEATURES + "namespace-prefixes").equals(name))
 169:       {
 170:         // NOOP
 171:       }
 172:     else if ((FEATURES + "string-interning").equals(name))
 173:       stringInterning = Boolean.TRUE.equals(value);
 174:     else if ((FEATURES + "use-attributes2").equals(name))
 175:       {
 176:         // NOOP
 177:       }
 178:     else if ((FEATURES + "validation").equals(name))
 179:       validating = Boolean.TRUE.equals(value);
 180:     else if ((FEATURES + "external-general-entities").equals(name))
 181:       externalEntities = Boolean.TRUE.equals(value);
 182:     else if ((FEATURES + "external-parameter-entities").equals(name))
 183:       externalEntities = Boolean.TRUE.equals(value);
 184:     else if ((PROPERTIES + "declaration-handler").equals(name))
 185:       declHandler = (DeclHandler) value;
 186:     else if ((PROPERTIES + "lexical-handler").equals(name))
 187:       lexicalHandler = (LexicalHandler) value;
 188:     else if ((GNU_FEATURES + "xml-base").equals(name))
 189:       baseAware = Boolean.TRUE.equals(value);
 190:     else if ((GNU_FEATURES + "coalescing").equals(name))
 191:       coalescing = Boolean.TRUE.equals(value);
 192:     else
 193:       throw new SAXNotSupportedException(name);
 194:   }
 195: 
 196:   public Object getProperty(String name)
 197:     throws SAXNotRecognizedException, SAXNotSupportedException
 198:   {
 199:     final String FEATURES = "http://xml.org/sax/features/";
 200:     final String PROPERTIES = "http://xml.org/sax/properties/";
 201:     final String GNU_FEATURES = "http://gnu.org/sax/features/";
 202:     final String GNU_PROPERTIES = "http://gnu.org/sax/properties/";
 203:     if ((GNU_FEATURES + "base-uri").equals(name))
 204:       return baseURI;
 205:     if ((FEATURES + "is-standalone").equals(name))
 206:       return xmlStandalone ? Boolean.TRUE : Boolean.FALSE;
 207:     if ((FEATURES + "namespaces").equals(name))
 208:       return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
 209:     if ((FEATURES + "namespace-prefixes").equals(name))
 210:       return Boolean.TRUE;
 211:     if ((FEATURES + "string-interning").equals(name))
 212:       return stringInterning ? Boolean.TRUE : Boolean.FALSE;
 213:     if ((FEATURES + "use-attributes2").equals(name))
 214:       return Boolean.TRUE;
 215:     if ((FEATURES + "use-locator2").equals(name))
 216:       return Boolean.TRUE;
 217:     if ((FEATURES + "use-entity-resolver2").equals(name))
 218:       return Boolean.FALSE;
 219:     if ((FEATURES + "validation").equals(name))
 220:       return validating ? Boolean.TRUE : Boolean.FALSE;
 221:     if ((FEATURES + "external-general-entities").equals(name))
 222:       return externalEntities ? Boolean.TRUE : Boolean.FALSE;
 223:     if ((FEATURES + "external-parameter-entities").equals(name))
 224:       return externalEntities ? Boolean.TRUE : Boolean.FALSE;
 225:     if ((FEATURES + "xml-1.1").equals(name))
 226:       return Boolean.TRUE;
 227:     if ((PROPERTIES + "declaration-handler").equals(name))
 228:       return declHandler;
 229:     if ((PROPERTIES + "document-xml-version").equals(name))
 230:       return xmlVersion;
 231:     if ((PROPERTIES + "lexical-handler").equals(name))
 232:       return lexicalHandler;
 233:     if ((GNU_FEATURES + "xml-base").equals(name))
 234:       return baseAware ? Boolean.TRUE : Boolean.FALSE;
 235:     if ((GNU_PROPERTIES + "document-xml-encoding").equals(name))
 236:       return xmlEncoding;
 237:     throw new SAXNotSupportedException(name);
 238:   }
 239: 
 240:   public boolean isXIncludeAware()
 241:   {
 242:     return xIncludeAware;
 243:   }
 244: 
 245:   public void reset()
 246:   {
 247:     parser = null;
 248:     encoding = null;
 249:     xmlVersion = null;
 250:     xmlStandalone = false;
 251:   }
 252: 
 253:   // -- XMLReader --
 254: 
 255:   public boolean getFeature(String name)
 256:     throws SAXNotRecognizedException, SAXNotSupportedException
 257:   {
 258:     Object ret = getProperty(name);
 259:     if (ret instanceof Boolean)
 260:       return ((Boolean) ret).booleanValue();
 261:     throw new SAXNotSupportedException(name);
 262:   }
 263: 
 264:   public void setFeature(String name, boolean value)
 265:     throws SAXNotRecognizedException, SAXNotSupportedException
 266:   {
 267:     setProperty(name, value ? Boolean.TRUE : Boolean.FALSE);
 268:   }
 269: 
 270:   public void setEntityResolver(EntityResolver resolver)
 271:   {
 272:     entityResolver = resolver;
 273:   }
 274: 
 275:   public EntityResolver getEntityResolver()
 276:   {
 277:     return entityResolver;
 278:   }
 279: 
 280:   public void setDTDHandler(DTDHandler handler)
 281:   {
 282:     dtdHandler = handler;
 283:   }
 284: 
 285:   public DTDHandler getDTDHandler()
 286:   {
 287:     return dtdHandler;
 288:   }
 289: 
 290:   public void setContentHandler(ContentHandler handler)
 291:   {
 292:     contentHandler = handler;
 293:   }
 294: 
 295:   public ContentHandler getContentHandler()
 296:   {
 297:     return contentHandler;
 298:   }
 299: 
 300:   public void setErrorHandler(ErrorHandler handler)
 301:   {
 302:     errorHandler = handler;
 303:   }
 304: 
 305:   public ErrorHandler getErrorHandler()
 306:   {
 307:     return errorHandler;
 308:   }
 309: 
 310:   public synchronized void parse(InputSource input)
 311:     throws IOException, SAXException
 312:   {
 313:     reset();
 314:     String systemId = input.getSystemId();
 315:     InputStream in = input.getByteStream();
 316:     boolean opened = false;
 317:     if (in != null)
 318:       parser = new XMLParser(in, systemId,
 319:                              validating,
 320:                              namespaceAware,
 321:                              coalescing,
 322:                              replaceERefs,
 323:                              externalEntities,
 324:                              supportDTD,
 325:                              baseAware,
 326:                              stringInterning,
 327:                              true,
 328:                              this,
 329:                              this);
 330:     else
 331:       {
 332:         Reader r = input.getCharacterStream();
 333:         if (r != null)
 334:           parser = new XMLParser(r, systemId,
 335:                                  validating,
 336:                                  namespaceAware,
 337:                                  coalescing,
 338:                                  replaceERefs,
 339:                                  externalEntities,
 340:                                  supportDTD,
 341:                                  baseAware,
 342:                                  stringInterning,
 343:                                  true,
 344:                                  this,
 345:                                  this);
 346:       }
 347:     if (parser == null)
 348:       {
 349:         if (systemId == null)
 350:           throw new SAXException("No stream or system ID specified");
 351:         systemId = XMLParser.absolutize(null, systemId);
 352:         in = new URL(systemId).openStream();
 353:         opened = true;
 354:         parser = new XMLParser(in, systemId,
 355:                                validating,
 356:                                namespaceAware,
 357:                                coalescing,
 358:                                replaceERefs,
 359:                                externalEntities,
 360:                                supportDTD,
 361:                                baseAware,
 362:                                stringInterning,
 363:                                true,
 364:                                this,
 365:                                this);
 366:       }
 367:     reader = parser;
 368:     baseURI = systemId;
 369:     
 370:     if (xIncludeAware)
 371:       reader = new XIncludeFilter(parser, systemId, namespaceAware,
 372:                                   validating, true);
 373:     
 374:     if (contentHandler != null)
 375:       contentHandler.setDocumentLocator(this);
 376:     boolean startDocumentDone = false;
 377:     try
 378:       {
 379:         while (parser.hasNext())
 380:           {
 381:             int event = parser.next();
 382:             if (baseAware)
 383:               baseURI = parser.getXMLBase();
 384:             switch (event)
 385:               {
 386:               case XMLStreamConstants.CHARACTERS:
 387:                 if (contentHandler != null)
 388:                   {
 389:                     char[] b = reader.getTextCharacters();
 390:                     contentHandler.characters(b, 0, b.length);
 391:                   }
 392:                 break;
 393:               case XMLStreamConstants.SPACE:
 394:                 if (contentHandler != null)
 395:                   {
 396:                     char[] b = reader.getTextCharacters();
 397:                     if (isIgnorableWhitespace(parser, b, false))
 398:                       contentHandler.ignorableWhitespace(b, 0, b.length);
 399:                     else
 400:                       contentHandler.characters(b, 0, b.length);
 401:                   }
 402:                 break;
 403:               case XMLStreamConstants.CDATA:
 404:                 if (lexicalHandler != null)
 405:                   lexicalHandler.startCDATA();
 406:                 if (contentHandler != null)
 407:                   {
 408:                     char[] b = reader.getTextCharacters();
 409:                     if (isIgnorableWhitespace(parser, b, true))
 410:                       contentHandler.ignorableWhitespace(b, 0, b.length);
 411:                     else
 412:                       contentHandler.characters(b, 0, b.length);
 413:                   }
 414:                 if (lexicalHandler != null)
 415:                   lexicalHandler.endCDATA();
 416:                 break;
 417:               case XMLStreamConstants.START_ELEMENT:
 418:                 if (contentHandler != null)
 419:                   {
 420:                     QName name = reader.getName();
 421:                     String uri = name.getNamespaceURI();
 422:                     String localName = name.getLocalPart();
 423:                     String prefix = name.getPrefix();
 424:                     String qName = localName;
 425:                     if (!"".equals(prefix))
 426:                       qName = prefix + ":" + localName;
 427:                     if (!namespaceAware)
 428:                       {
 429:                         uri = "";
 430:                         localName = "";
 431:                       }
 432:                     else
 433:                       {
 434:                         int nc = reader.getNamespaceCount();
 435:                         for (int i = 0; i < nc; i++)
 436:                           {
 437:                             String nsuri = reader.getNamespaceURI(i);
 438:                             String nsprefix = reader.getNamespacePrefix(i);
 439:                             if ("xml".equals(nsprefix))
 440:                               continue;
 441:                             contentHandler.startPrefixMapping(nsprefix, nsuri);
 442:                           }
 443:                       }
 444:                     contentHandler.startElement(uri, localName, qName, this);
 445:                   }
 446:                 break;
 447:               case XMLStreamConstants.END_ELEMENT:
 448:                 if (contentHandler != null)
 449:                   {
 450:                     QName name = reader.getName();
 451:                     String uri = name.getNamespaceURI();
 452:                     String localName = name.getLocalPart();
 453:                     String prefix = name.getPrefix();
 454:                     String qName = localName;
 455:                     if (!"".equals(prefix))
 456:                       qName = prefix + ":" + localName;
 457:                     if (!namespaceAware)
 458:                       {
 459:                         uri = "";
 460:                         localName = "";
 461:                       }
 462:                     contentHandler.endElement(uri, localName, qName);
 463:                     if (namespaceAware)
 464:                       {
 465:                         int nc = reader.getNamespaceCount();
 466:                         for (int i = 0; i < nc; i++)
 467:                           {
 468:                             String nsprefix = reader.getNamespacePrefix(i);
 469:                             if ("xml".equals(nsprefix))
 470:                               continue;
 471:                             contentHandler.endPrefixMapping(nsprefix);
 472:                           }
 473:                       }
 474:                   }
 475:                 break;
 476:               case XMLStreamConstants.COMMENT:
 477:                 if (lexicalHandler != null)
 478:                   {
 479:                     char[] b = reader.getTextCharacters();
 480:                     lexicalHandler.comment(b, 0, b.length);
 481:                   }
 482:                 break;
 483:               case XMLStreamConstants.PROCESSING_INSTRUCTION:
 484:                 if (contentHandler != null)
 485:                   {
 486:                     String target = reader.getPITarget();
 487:                     String data = reader.getPIData();
 488:                     if (data == null)
 489:                       data = "";
 490:                     contentHandler.processingInstruction(target, data);
 491:                   }
 492:                 break;
 493:               case XMLParser.START_ENTITY:
 494:                 if (lexicalHandler != null)
 495:                   {
 496:                     String name = reader.getText();
 497:                     lexicalHandler.startEntity(name);
 498:                   }
 499:                 break;
 500:               case XMLParser.END_ENTITY:
 501:                 if (lexicalHandler != null)
 502:                   {
 503:                     String name = reader.getText();
 504:                     lexicalHandler.endEntity(name);
 505:                   }
 506:                 break;
 507:               case XMLStreamConstants.START_DOCUMENT:
 508:                 encoding = reader.getEncoding();
 509:                 xmlVersion = reader.getVersion();
 510:                 xmlStandalone = reader.isStandalone();
 511:                 xmlEncoding = reader.getCharacterEncodingScheme();
 512:                 if (contentHandler != null)
 513:                   contentHandler.startDocument();
 514:                 startDocumentDone = true;
 515:                 break;
 516:               case XMLStreamConstants.END_DOCUMENT:
 517:                 if (contentHandler != null)
 518:                   contentHandler.endDocument();
 519:                 break;
 520:               case XMLStreamConstants.DTD:
 521:                 XMLParser.Doctype doctype = parser.doctype;
 522:                 if (lexicalHandler != null)
 523:                   {
 524:                     String rootName = doctype.rootName;
 525:                     String publicId = doctype.publicId;
 526:                     String systemId2 = doctype.systemId;
 527:                     lexicalHandler.startDTD(rootName, publicId, systemId2);
 528:                   }
 529:                 for (Iterator i = doctype.entryIterator(); i.hasNext(); )
 530:                   {
 531:                     String entry = (String) i.next();
 532:                     char c = entry.charAt(0);
 533:                     String name = entry.substring(1);
 534:                     if ('E' == c)
 535:                       {
 536:                         // Element decl
 537:                         if (declHandler != null)
 538:                           {
 539:                             XMLParser.ContentModel model =
 540:                               doctype.getElementModel(name);
 541:                             declHandler.elementDecl(name, model.text);
 542:                           }
 543:                       }
 544:                     else if ('A' == c)
 545:                       {
 546:                         // Attlist decl
 547:                         if (declHandler != null)
 548:                           {
 549:                             for (Iterator j = doctype.attlistIterator(name);
 550:                                  j.hasNext(); )
 551:                               {
 552:                                 Map.Entry att = (Map.Entry) j.next();
 553:                                 String aname = (String) att.getKey();
 554:                                 XMLParser.AttributeDecl decl =
 555:                                   (XMLParser.AttributeDecl) att.getValue();
 556:                                 String type = decl.type;
 557:                                 String value = decl.value;
 558:                                 String mode = null;
 559:                                 switch (decl.valueType)
 560:                                   {
 561:                                   case XMLParser.ATTRIBUTE_DEFAULT_FIXED:
 562:                                     mode = "#FIXED";
 563:                                     break;
 564:                                   case XMLParser.ATTRIBUTE_DEFAULT_REQUIRED:
 565:                                     mode = "#REQUIRED";
 566:                                     break;
 567:                                   case XMLParser.ATTRIBUTE_DEFAULT_IMPLIED:
 568:                                     mode = "#IMPLIED";
 569:                                     break;
 570:                                   }
 571:                                 declHandler.attributeDecl(name, aname,
 572:                                                           type, mode, value);
 573:                               }
 574:                           }
 575:                       }
 576:                     else if ('e' == c)
 577:                       {
 578:                         // Entity decl
 579:                         Object entity = doctype.getEntity(name);
 580:                         if (entity instanceof String)
 581:                           {
 582:                             if (declHandler != null)
 583:                               declHandler.internalEntityDecl(name,
 584:                                                              (String) entity);
 585:                           }
 586:                         else
 587:                           {
 588:                             XMLParser.ExternalIds ids =
 589:                               (XMLParser.ExternalIds) entity;
 590:                             if (ids.notationName != null)
 591:                               {
 592:                                 if (dtdHandler != null)
 593:                                   {
 594:                                     String pub = ids.publicId;
 595:                                     String url = ids.systemId;
 596:                                     String not = ids.notationName;
 597:                                     dtdHandler.unparsedEntityDecl(name,
 598:                                                                   pub,
 599:                                                                   url,
 600:                                                                   not);
 601:                                   }
 602:                               }
 603:                             else
 604:                               {
 605:                                 if (declHandler != null)
 606:                                   {
 607:                                     String pub = ids.publicId;
 608:                                     String url = ids.systemId;
 609:                                     declHandler.externalEntityDecl(name,
 610:                                                                    pub,
 611:                                                                    url);
 612:                                   }
 613:                               }
 614:                           }
 615:                       }
 616:                     else if ('n' == c)
 617:                       {
 618:                         // Notation decl
 619:                         if (dtdHandler != null)
 620:                           {
 621:                             XMLParser.ExternalIds ids =
 622:                               doctype.getNotation(name);
 623:                             String pub = ids.publicId;
 624:                             String url = ids.systemId;
 625:                             dtdHandler.notationDecl(name, pub, url);
 626:                           }
 627:                       }
 628:                     else if ('c' == c)
 629:                       {
 630:                         // Comment
 631:                         if (lexicalHandler != null)
 632:                           {
 633:                             String comment = doctype.getComment(name);
 634:                             char[] b = comment.toCharArray();
 635:                             lexicalHandler.comment(b, 0, b.length);
 636:                           }
 637:                       }
 638:                     else if ('p' == c)
 639:                       {
 640:                         // Processing instruction
 641:                         if (contentHandler != null)
 642:                           {
 643:                             String[] pi = doctype.getPI(name);
 644:                             String target = pi[0];
 645:                             String data = pi[1];
 646:                             if (data == null)
 647:                               data = "";
 648:                             contentHandler.processingInstruction(target, data);
 649:                           }
 650:                       }
 651:                   }
 652:                 if (lexicalHandler != null)
 653:                   lexicalHandler.endDTD();
 654:               }
 655:           }
 656:         reset();
 657:         if (opened)
 658:           in.close();
 659:       }
 660:     catch (Exception e)
 661:       {
 662:         SAXParseException e2 = new SAXParseException(e.getMessage(), this);
 663:         e2.initCause(e);
 664:         try
 665:           {
 666:             if (!startDocumentDone && contentHandler != null)
 667:               contentHandler.startDocument();
 668:             if (errorHandler != null)
 669:               errorHandler.fatalError(e2);
 670:             if (contentHandler != null)
 671:               contentHandler.endDocument();
 672:           }
 673:         catch (SAXException sex)
 674:           {
 675:             // Ignored, we will rethrow the original exception.
 676:           }
 677:         reset();
 678:         if (opened)
 679:           in.close();
 680:         if (e instanceof SAXException)
 681:           throw (SAXException) e;
 682:         if (e instanceof IOException)
 683:           throw (IOException) e;
 684:         else
 685:           throw e2;
 686:       }
 687:   }
 688: 
 689:   /**
 690:    * Indicates whether the specified characters are ignorable whitespace.
 691:    */
 692:   private boolean isIgnorableWhitespace(XMLParser reader, char[] b,
 693:                                         boolean testCharacters)
 694:     throws XMLStreamException
 695:   {
 696:     XMLParser.Doctype doctype = reader.doctype;
 697:     if (doctype == null)
 698:       return false;
 699:     String currentElement = reader.getCurrentElement();
 700:     // check for xml:space
 701:     int ac = reader.getAttributeCount();
 702:     for (int i = 0; i < ac; i++)
 703:       {
 704:         QName aname = reader.getAttributeName(i);
 705:         if ("space".equals(aname.getLocalPart()) &&
 706:             XMLConstants.XML_NS_URI.equals(aname.getNamespaceURI()))
 707:           {
 708:             if ("preserve".equals(reader.getAttributeValue(i)))
 709:               return false;
 710:           }
 711:       }
 712:     XMLParser.ContentModel model = doctype.getElementModel(currentElement);
 713:     if (model == null || model.type != XMLParser.ContentModel.ELEMENT)
 714:       return false;
 715:     if (model.external && xmlStandalone)
 716:       return false;
 717:     boolean white = true;
 718:     if (testCharacters)
 719:       {
 720:         for (int i = 0; i < b.length; i++)
 721:           {
 722:             if (b[i] != ' ' && b[i] != '\t' && b[i] != '\n' && b[i] != '\r')
 723:               {
 724:                 white = false;
 725:                 break;
 726:               }
 727:           }
 728:       }
 729:     return white;
 730:   }
 731: 
 732:   public void parse(String systemId)
 733:     throws IOException, SAXException
 734:   {
 735:     parse(new InputSource(systemId));
 736:   }
 737: 
 738:   // -- Attributes2 --
 739: 
 740:   public int getIndex(String qName)
 741:   {
 742:     int len = reader.getAttributeCount();
 743:     for (int i = 0; i < len; i++)
 744:       {
 745:         QName q = reader.getAttributeName(i);
 746:         String localName = q.getLocalPart();
 747:         String prefix = q.getPrefix();
 748:         String qn = ("".equals(prefix)) ? localName : prefix + ":" + localName;
 749:         if (qName.equals(qn))
 750:           return i;
 751:       }
 752:     return -1;
 753:   }
 754: 
 755:   public int getIndex(String uri, String localName)
 756:   {
 757:     int len = reader.getAttributeCount();
 758:     for (int i = 0; i < len; i++)
 759:       {
 760:         QName q = reader.getAttributeName(i);
 761:         String ln = q.getLocalPart();
 762:         String u = q.getNamespaceURI();
 763:         if (u == null && uri != null)
 764:           continue;
 765:         if (u != null && !u.equals(uri))
 766:           continue;
 767:         if (ln.equals(localName))
 768:           return i;
 769:       }
 770:     return -1;
 771:   }
 772: 
 773:   public int getLength()
 774:   {
 775:     return reader.getAttributeCount();
 776:   }
 777: 
 778:   public String getLocalName(int index)
 779:   {
 780:     return reader.getAttributeLocalName(index);
 781:   }
 782: 
 783:   public String getQName(int index)
 784:   {
 785:     QName q = reader.getAttributeName(index);
 786:     String localName = q.getLocalPart();
 787:     String prefix = q.getPrefix();
 788:     return ("".equals(prefix)) ? localName : prefix + ":" + localName;
 789:   }
 790: 
 791:   public String getType(int index)
 792:   {
 793:     String ret = reader.getAttributeType(index);
 794:     // SAX doesn't permit ENUMERATION?
 795:     return ("ENUMERATION".equals(ret)) ? "NMTOKEN" : ret;
 796:   }
 797: 
 798:   public String getType(String qName)
 799:   {
 800:     int index = getIndex(qName);
 801:     return (index == -1) ? null : getType(index);
 802:   }
 803: 
 804:   public String getType(String uri, String localName)
 805:   {
 806:     int index = getIndex(uri, localName);
 807:     return (index == -1) ? null : getType(index);
 808:   }
 809: 
 810:   public String getURI(int index)
 811:   {
 812:     String ret = reader.getAttributeNamespace(index);
 813:     return (ret == null) ? "" : ret;
 814:   }
 815: 
 816:   public String getValue(int index)
 817:   {
 818:     return reader.getAttributeValue(index);
 819:   }
 820: 
 821:   public String getValue(String qName)
 822:   {
 823:     int index = getIndex(qName);
 824:     return (index == -1) ? null : getValue(index);
 825:   }
 826: 
 827:   public String getValue(String uri, String localName)
 828:   {
 829:     int index = getIndex(uri, localName);
 830:     return (index == -1) ? null : getValue(index);
 831:   }
 832: 
 833:   public boolean isDeclared(int index)
 834:   {
 835:     return parser.isAttributeDeclared(index);
 836:   }
 837: 
 838:   public boolean isDeclared(String qName)
 839:   {
 840:     int index = getIndex(qName);
 841:     return (index == -1) ? false : isDeclared(index);
 842:   }
 843: 
 844:   public boolean isDeclared(String uri, String localName)
 845:   {
 846:     int index = getIndex(uri, localName);
 847:     return (index == -1) ? false : isDeclared(index);
 848:   }
 849: 
 850:   public boolean isSpecified(int index)
 851:   {
 852:     return reader.isAttributeSpecified(index);
 853:   }
 854: 
 855:   public boolean isSpecified(String qName)
 856:   {
 857:     int index = getIndex(qName);
 858:     return (index == -1) ? false : isSpecified(index);
 859:   }
 860: 
 861:   public boolean isSpecified(String uri, String localName)
 862:   {
 863:     int index = getIndex(uri, localName);
 864:     return (index == -1) ? false : isSpecified(index);
 865:   }
 866: 
 867:   // -- Locator2 --
 868:   
 869:   public int getColumnNumber()
 870:   {
 871:     Location l = reader.getLocation();
 872:     return l.getColumnNumber();
 873:   }
 874: 
 875:   public int getLineNumber()
 876:   {
 877:     Location l = reader.getLocation();
 878:     return l.getLineNumber();
 879:   }
 880: 
 881:   public String getPublicId()
 882:   {
 883:     Location l = reader.getLocation();
 884:     return l.getPublicId();
 885:   }
 886: 
 887:   public String getSystemId()
 888:   {
 889:     Location l = reader.getLocation();
 890:     return l.getSystemId();
 891:   }
 892:   
 893:   public String getEncoding()
 894:   {
 895:     return encoding;
 896:   }
 897: 
 898:   public String getXMLVersion()
 899:   {
 900:     return xmlVersion;
 901:   }
 902: 
 903:   // -- XMLResolver --
 904:   
 905:   public Object resolveEntity(String publicId, String systemId,
 906:                               String baseURI, String namespace)
 907:     throws XMLStreamException
 908:   {
 909:     if (entityResolver != null)
 910:       {
 911:         try
 912:           {
 913:             InputSource input =
 914:               entityResolver.resolveEntity(publicId, systemId);
 915:             if (input != null)
 916:               {
 917:                 InputStream in = input.getByteStream();
 918:                 if (in == null)
 919:                   {
 920:                     String newSystemId = input.getSystemId();
 921:                     if (newSystemId != null && !newSystemId.equals(systemId))
 922:                       in = XMLParser.resolve(newSystemId);
 923:                   }
 924:                 return in;
 925:               }
 926:           }
 927:         catch (SAXException e)
 928:           {
 929:             XMLStreamException e2 = new XMLStreamException(e.getMessage());
 930:             e2.initCause(e);
 931:             throw e2;
 932:           }
 933:         catch (IOException e)
 934:           {
 935:             XMLStreamException e2 = new XMLStreamException(e.getMessage());
 936:             e2.initCause(e);
 937:             throw e2;
 938:           }
 939:       }
 940:     return null;
 941:   }
 942: 
 943:   public XMLEventReader resolveAsXMLEventReader(String uri)
 944:     throws XMLStreamException
 945:   {
 946:     // unused
 947:     return null;
 948:   }
 949: 
 950:   public XMLStreamReader resolveAsXMLStreamReader(String uri)
 951:     throws XMLStreamException
 952:   {
 953:     // unused
 954:     return null;
 955:   }
 956: 
 957:   // -- XMLReporter --
 958: 
 959:   public void report(String message, String errorType,
 960:                      Object relatedInformation, Location location)
 961:     throws XMLStreamException
 962:   {
 963:     if (errorHandler != null)
 964:       {
 965:         try
 966:           {
 967:             errorHandler.warning(new SAXParseException(message, this));
 968:           }
 969:         catch (SAXException e)
 970:           {
 971:             XMLStreamException e2 = new XMLStreamException(e.getMessage());
 972:             e2.initCause(e);
 973:             throw e2;
 974:           }
 975:       }
 976:   }
 977: 
 978:   public static void main(String[] args)
 979:     throws Exception
 980:   {
 981:     boolean validating = false;
 982:     boolean namespaceAware = false;
 983:     boolean xIncludeAware = false;
 984:     boolean expectCallbackClass = false;
 985:     String callbackClass = null;
 986:     int pos = 0;
 987:     while (pos < args.length && (args[pos].startsWith("-") || expectCallbackClass))
 988:       {
 989:         if ("-x".equals(args[pos]))
 990:           xIncludeAware = true;
 991:         else if ("-v".equals(args[pos]))
 992:           validating = true;
 993:         else if ("-n".equals(args[pos]))
 994:           namespaceAware = true;
 995:         else if ("-c".equals(args[pos]))
 996:           expectCallbackClass = true;
 997:         else if (expectCallbackClass)
 998:           {
 999:             callbackClass = args[pos];
1000:             expectCallbackClass = false;
1001:           }
1002:         pos++;
1003:       }
1004:     if (pos >= args.length || expectCallbackClass)
1005:       {
1006:         System.out.println("Syntax: SAXParser [-n] [-v] [-x] [-c <class>] <file> [<file2> [...]]");
1007:         System.out.println("\t-n: use namespace aware mode");
1008:         System.out.println("\t-v: use validating parser");
1009:         System.out.println("\t-x: use XInclude aware mode");
1010:         System.out.println("\t-c <class>: use specified class as callback handler (must have a no-arg public constructor)");
1011:         System.exit(2);
1012:       }
1013:     while (pos < args.length)
1014:       {
1015:         ContentHandler handler = null;
1016:         if (callbackClass != null)
1017:           {
1018:             Class t = Class.forName(callbackClass);
1019:             handler = (ContentHandler) t.newInstance();
1020:           }
1021:         else
1022:           handler = new org.xml.sax.helpers.DefaultHandler();
1023:         SAXParser parser = new SAXParser(validating, namespaceAware,
1024:                                          xIncludeAware);
1025:         InputSource input = new InputSource(args[pos]);
1026:         java.io.FileReader fr = new java.io.FileReader(args[pos]);
1027:         input.setCharacterStream(fr);
1028:         try
1029:           {
1030:             XMLReader reader = parser.getXMLReader();
1031:             reader.setContentHandler(handler);
1032:             reader.parse(input);
1033:           }
1034:         finally
1035:           {
1036:             fr.close();
1037:           }
1038:         pos++;
1039:       }
1040:   }
1041:   
1042: }