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