Clover coverage report - Clover results for XOM 1.2d1
Coverage timestamp: Wed Feb 8 2006 08:31:33 EST
file stats: LOC: 3,307   Methods: 172
NCLOC: 2,409   Classes: 15
Warning
The source file used to generate this report was changed after Clover generated coverage information. The coverage reported may not match the source lines. You should regenerate the coverage information and the report to ensure the files are in sync.
 
 Source file Conditionals Statements Methods TOTAL
BuilderTest.java 71.2% 93.3% 98.8% 92.8%
coverage coverage
 1    /* Copyright 2002-2005 Elliotte Rusty Harold
 2   
 3    This library is free software; you can redistribute it and/or modify
 4    it under the terms of version 2.1 of the GNU Lesser General Public
 5    License as published by the Free Software Foundation.
 6   
 7    This library is distributed in the hope that it will be useful,
 8    but WITHOUT ANY WARRANTY; without even the implied warranty of
 9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 10    GNU Lesser General Public License for more details.
 11   
 12    You should have received a copy of the GNU Lesser General Public
 13    License along with this library; if not, write to the
 14    Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 15    Boston, MA 02111-1307 USA
 16   
 17    You can contact Elliotte Rusty Harold by sending e-mail to
 18    elharo@metalab.unc.edu. Please include the word "XOM" in the
 19    subject line. The XOM home page is located at http://www.xom.nu/
 20    */
 21   
 22    package nu.xom.tests;
 23   
 24    import java.io.ByteArrayOutputStream;
 25    import java.io.CharConversionException;
 26    import java.io.File;
 27    import java.io.FileNotFoundException;
 28    import java.io.FileOutputStream;
 29    import java.io.IOException;
 30    import java.io.OutputStreamWriter;
 31    import java.io.PrintStream;
 32    import java.io.Reader;
 33    import java.io.StringReader;
 34    import java.io.ByteArrayInputStream;
 35    import java.io.InputStream;
 36    import java.io.UTFDataFormatException;
 37    import java.io.Writer;
 38    import java.lang.ref.WeakReference;
 39    import java.lang.reflect.Constructor;
 40    import java.lang.reflect.InvocationTargetException;
 41   
 42    import org.xml.sax.Attributes;
 43    import org.xml.sax.InputSource;
 44    import org.xml.sax.Locator;
 45    import org.xml.sax.SAXException;
 46    import org.xml.sax.SAXNotRecognizedException;
 47    import org.xml.sax.SAXNotSupportedException;
 48    import org.xml.sax.SAXParseException;
 49    import org.xml.sax.XMLFilter;
 50    import org.xml.sax.XMLReader;
 51    import org.xml.sax.helpers.AttributesImpl;
 52    import org.xml.sax.helpers.LocatorImpl;
 53    import org.xml.sax.helpers.XMLFilterImpl;
 54    import org.xml.sax.helpers.XMLReaderFactory;
 55   
 56    import nu.xom.Attribute;
 57    import nu.xom.Builder;
 58    import nu.xom.Comment;
 59    import nu.xom.DocType;
 60    import nu.xom.Document;
 61    import nu.xom.Element;
 62    import nu.xom.Elements;
 63    import nu.xom.NodeFactory;
 64    import nu.xom.ParsingException;
 65    import nu.xom.ProcessingInstruction;
 66    import nu.xom.Serializer;
 67    import nu.xom.ValidityException;
 68    import nu.xom.WellformednessException;
 69    import nu.xom.XMLException;
 70   
 71   
 72    /**
 73    * <p>
 74    * Tests building documents from streams, strings, files,
 75    * and other input sources.
 76    * </p>
 77    *
 78    * @author Elliotte Rusty Harold
 79    * @version 1.2b1
 80    *
 81    */
 82    public class BuilderTest extends XOMTestCase {
 83   
 84   
 85    private File inputDir = new File("data");
 86   
 87    // This class tests error conditions, which Xerces
 88    // annoyingly logs to System.err. So we hide System.err
 89    // before each test and restore it after each test.
 90    private PrintStream systemErr = System.err;
 91   
 92  143 protected void setUp() {
 93  143 System.setErr(new PrintStream(new ByteArrayOutputStream()));
 94    }
 95   
 96   
 97  143 protected void tearDown() {
 98  143 System.setErr(systemErr);
 99    }
 100   
 101   
 102    // Custom parser to test what happens when parser supplies
 103    // malformed data
 104    private static class CustomReader extends XMLFilterImpl {
 105   
 106  25 public void setFeature(String name, boolean value) {};
 107   
 108  1 public void parse(InputSource in) throws SAXException {
 109  1 this.getContentHandler().startDocument();
 110  1 this.getContentHandler().startElement("87", "87", "87", new AttributesImpl());
 111  0 this.getContentHandler().endElement("87", "87", "87");
 112  0 this.getContentHandler().endDocument();
 113    }
 114   
 115    }
 116   
 117   
 118    private static class DoNothingReader extends CustomReader {
 119   
 120  1 public void parse(InputSource in) throws SAXException {}
 121   
 122    }
 123   
 124   
 125    private static class StartAndEndReader extends CustomReader {
 126   
 127  1 public void parse(InputSource in) throws SAXException {
 128  1 this.getContentHandler().startDocument();
 129  1 this.getContentHandler().endDocument();
 130    }
 131   
 132    }
 133   
 134   
 135    private static class StartOnlyReader extends CustomReader {
 136   
 137  1 public void parse(InputSource in) throws SAXException {
 138  1 this.getContentHandler().startDocument();
 139    }
 140   
 141    }
 142   
 143   
 144    private static class EndOnlyReader extends CustomReader {
 145   
 146  1 public void parse(InputSource in) throws SAXException {
 147  1 this.getContentHandler().endDocument();
 148    }
 149   
 150    }
 151   
 152   
 153  143 public BuilderTest(String name) {
 154  143 super(name);
 155    }
 156   
 157   
 158    // flag to turn on and off tests based on
 159    // http://nagoya.apache.org/bugzilla/show_bug.cgi?id=24124
 160    private boolean xercesBroken = false;
 161   
 162    private String elementDeclaration = "<!ELEMENT root (#PCDATA)>";
 163    private String defaultAttributeDeclaration
 164    = "<!ATTLIST test name CDATA \"value\">";
 165    private String attributeDeclaration
 166    = "<!ATTLIST root anattribute CDATA #REQUIRED>";
 167    private String attributeDeclaration2
 168    = "<!ATTLIST root anotherattribute CDATA \"value\">";
 169    private String unparsedEntityDeclaration
 170    = "<!ENTITY hatch-pic SYSTEM " +
 171    "\"http://www.example.com/images/cup.gif\" NDATA gif>";
 172    private String unparsedEntityDeclarationPublic
 173    = "<!ENTITY public-pic PUBLIC \"public ID\" " +
 174    "\"http://www.example.com/images/cup.gif\" NDATA gif>";
 175    private String internalEntityDeclaration
 176    = "<!ENTITY Pub-Status \"" +
 177    "This is a pre-release of the specification.\">";
 178    private String externalEntityDeclarationPublic =
 179    "<!ENTITY open-hatch "
 180    + "PUBLIC \"-//Textuality//TEXT Standard " +
 181    "open-hatch boilerplate//EN\" "
 182    + "\"http://www.textuality.com/boilerplate/OpenHatch.xml\">";
 183    private String externalEntityDeclarationSystem =
 184    "<!ENTITY test SYSTEM " +
 185    "\"http://www.textuality.com/boilerplate/OpenHatch.xml\">";
 186    private String notationDeclarationSystem
 187    = "<!NOTATION ISODATE SYSTEM "
 188    + "\"http://www.iso.ch/cate/d15903.html\">";
 189    private String notationDeclarationPublicAndSystem
 190    = "<!NOTATION DATE PUBLIC \"DATE PUBLIC ID\" "
 191    + "\"http://www.iso.ch/cate/d15903.html\">";
 192    private String notationDeclarationPublic = "<!NOTATION gif PUBLIC "
 193    + "\"-//Textuality//TEXT Standard open-hatch boilerplate//EN\">";
 194   
 195    private String source = "<!DOCTYPE test [\r\n"
 196    + elementDeclaration + "\n"
 197    + attributeDeclaration + "\n"
 198    + defaultAttributeDeclaration + "\n"
 199    + attributeDeclaration2 + "\n"
 200    + internalEntityDeclaration + "\n"
 201    + externalEntityDeclarationPublic + "\n"
 202    + externalEntityDeclarationSystem + "\n"
 203    + unparsedEntityDeclaration + "\n"
 204    + unparsedEntityDeclarationPublic + "\n"
 205    + notationDeclarationPublic + "\n"
 206    + notationDeclarationSystem + "\n"
 207    + notationDeclarationPublicAndSystem + "\n"
 208    + "]>\r\n"
 209    + "<?xml-stylesheet href=\"file.css\" type=\"text/css\"?>"
 210    + "<!-- test -->"
 211    + "<test xmlns:xlink='http://www.w3.org/TR/1999/xlink'>Hello dear"
 212    + "\r\n<em id=\"p1\" xmlns:none=\"http://www.example.com\">"
 213    + "very important</em>"
 214    + "<span xlink:type='simple'>here&apos;s the link</span>\r\n"
 215    + "<svg:svg xmlns:svg='http://www.w3.org/TR/2000/svg'>"
 216    + "<svg:text>text in a namespace</svg:text></svg:svg>\r\n"
 217    + "<svg xmlns='http://www.w3.org/TR/2000/svg'><text>text in a "
 218    + "namespace</text></svg></test>\r\n<!--epilog-->";
 219   
 220    private String validDoc = "<!DOCTYPE test [\r\n"
 221    + "<!ELEMENT test (#PCDATA)>\n"
 222    + "]>\r\n"
 223    + "<?xml-stylesheet href=\"file.css\" type=\"text/css\"?>"
 224    + "<!-- test -->"
 225    + "<test>Hello dear</test>"
 226    + "<!--epilog-->";
 227   
 228    private Builder builder = new Builder();
 229    private Builder validator = new Builder(true);
 230    private String base = "http://www.example.com/";
 231   
 232    private String attributeDoc = "<!DOCTYPE test [\n"
 233    + "<!ELEMENT test (#PCDATA)>\n"
 234    + "<!NOTATION GIF SYSTEM \"text/gif\">\n"
 235    + "<!ENTITY data SYSTEM \"http://www.example.org/cup.gif\">\n"
 236    + "<!ATTLIST test notationatt NOTATION (GIF) \"GIF\">\n"
 237    + "<!ATTLIST test cdataatt CDATA \"GIF\">\n"
 238    + "<!ATTLIST test entityatt ENTITY \"data\">\n"
 239    + "<!ATTLIST test entitiesatt ENTITIES \"data\">\n"
 240    + "<!ATTLIST test nmtokenatt NMTOKEN \" 1 \">\n"
 241    + "<!ATTLIST test nmtokensatt NMTOKENS \" 1 2 3 \">\n"
 242    + "<!ATTLIST test idatt ID \" p1 \">\n"
 243    + "<!ATTLIST test idrefatt IDREF \" p1 \">\n"
 244    + "<!ATTLIST test idrefsatt IDREFS \" p1 p2 \">\n"
 245    + "]>\r\n"
 246    + "<test>Hello dear</test>";
 247   
 248   
 249  1 public void testDoNothingParser()
 250    throws ParsingException, IOException {
 251   
 252  1 try {
 253  1 XMLReader parser = new DoNothingReader();
 254  1 Builder builder = new Builder(parser);
 255  1 builder.build("http://www.example.org/");
 256  0 fail("built from bad data");
 257    }
 258    catch (ParsingException success) {
 259  1 assertNotNull(success.getMessage());
 260  1 assertEquals("http://www.example.org/", success.getURI());
 261    }
 262   
 263    }
 264   
 265   
 266  1 public void testStartAndEndParser()
 267    throws ParsingException, IOException {
 268   
 269  1 XMLReader parser = new StartAndEndReader();
 270  1 Builder builder = new Builder(parser);
 271  1 Document doc = builder.build("http://www.example.org/");
 272  1 assertNotNull(doc.getRootElement());
 273   
 274    }
 275   
 276   
 277  1 public void testStartOnlyParser()
 278    throws ParsingException, IOException {
 279   
 280  1 XMLReader parser = new StartOnlyReader();
 281  1 Builder builder = new Builder(parser);
 282  1 Document doc = builder.build("http://www.example.org/");
 283  1 assertNotNull(doc.getRootElement());
 284   
 285    }
 286   
 287   
 288  1 public void testEndOnlyParser()
 289    throws ParsingException, IOException {
 290   
 291  1 try {
 292  1 XMLReader parser = new EndOnlyReader();
 293  1 Builder builder = new Builder(parser);
 294  1 builder.build("http://www.example.org/");
 295  0 fail("built from bad data");
 296    }
 297    catch (ParsingException success) {
 298  1 assertTrue(success.getCause() instanceof NullPointerException);
 299    }
 300   
 301    }
 302   
 303   
 304  1 public void testBuildInternalDTDSubsetWithFixedDefaultAttributeValue()
 305    throws ParsingException, IOException {
 306   
 307  1 String doctype = "<!DOCTYPE xsl:stylesheet [\n"
 308    + "<!ATTLIST a b CDATA #FIXED \"c\">]>";
 309  1 String document = doctype + "\n<root/>";
 310  1 Builder builder = new Builder();
 311  1 Document doc = builder.build(document, null);
 312  1 DocType dt = doc.getDocType();
 313  1 String internalDTDSubset = dt.getInternalDTDSubset();
 314  1 assertTrue(internalDTDSubset.indexOf("#FIXED \"c\"") > 0);
 315   
 316    }
 317   
 318   
 319  1 public void testNotationAttributeType()
 320    throws IOException, ParsingException {
 321   
 322  1 Reader reader = new StringReader(attributeDoc);
 323  1 Document document = builder.build(reader);
 324  1 Element root = document.getRootElement();
 325  1 Attribute att = root.getAttribute("notationatt");
 326  1 assertEquals(Attribute.Type.NOTATION, att.getType());
 327   
 328    }
 329   
 330   
 331  1 public void testCDATAAttributeType()
 332    throws IOException, ParsingException {
 333   
 334  1 Reader reader = new StringReader(attributeDoc);
 335  1 Document document = builder.build(reader);
 336  1 Element root = document.getRootElement();
 337  1 Attribute att = root.getAttribute("cdataatt");
 338  1 assertEquals(Attribute.Type.CDATA, att.getType());
 339   
 340    }
 341   
 342   
 343  1 public void testEntityAttributeType()
 344    throws IOException, ParsingException {
 345   
 346  1 Reader reader = new StringReader(attributeDoc);
 347  1 Document document = builder.build(reader);
 348  1 Element root = document.getRootElement();
 349  1 Attribute att = root.getAttribute("entityatt");
 350  1 assertEquals(Attribute.Type.ENTITY, att.getType());
 351   
 352    }
 353   
 354   
 355  1 public void testEntitiesAttributeType()
 356    throws IOException, ParsingException {
 357   
 358  1 Reader reader = new StringReader(attributeDoc);
 359  1 Document document = builder.build(reader);
 360  1 Element root = document.getRootElement();
 361  1 Attribute att = root.getAttribute("entitiesatt");
 362  1 assertEquals(Attribute.Type.ENTITIES, att.getType());
 363   
 364    }
 365   
 366   
 367  1 public void testNameTokenAttributeType()
 368    throws IOException, ParsingException {
 369   
 370  1 Reader reader = new StringReader(attributeDoc);
 371  1 Document document = builder.build(reader);
 372  1 Element root = document.getRootElement();
 373  1 Attribute att = root.getAttribute("nmtokenatt");
 374  1 assertEquals(Attribute.Type.NMTOKEN, att.getType());
 375  1 assertEquals("1", att.getValue());
 376   
 377    }
 378   
 379   
 380    // I'm specifically worried about a Xerces runtime MalformedURIException here
 381  1 public void testIllegalSystemIDThrowsRightException() {
 382   
 383  1 String document = "<!DOCTYPE root SYSTEM \"This is not a URI\"><root/>";
 384  1 try{
 385  1 builder.build(document, null);
 386    }
 387    catch (Exception ex) {
 388  1 assertTrue(ex instanceof ParsingException);
 389    }
 390   
 391    }
 392   
 393   
 394  1 public void testNameTokensAttributeType()
 395    throws IOException, ParsingException {
 396   
 397  1 Reader reader = new StringReader(attributeDoc);
 398  1 Document document = builder.build(reader);
 399  1 Element root = document.getRootElement();
 400  1 Attribute att = root.getAttribute("nmtokensatt");
 401  1 assertEquals(Attribute.Type.NMTOKENS, att.getType());
 402  1 assertEquals("1 2 3", att.getValue());
 403   
 404    }
 405   
 406   
 407    // verify that XML 1.1 is not supported
 408  1 public void testXML11() throws IOException {
 409   
 410  1 String data = "<?xml version='1.1'?><root/>";
 411  1 try {
 412  1 builder.build(data, "http://www.example.com");
 413  0 fail("XML 1.1 allowed");
 414    }
 415    catch (ParsingException ex) {
 416  1 assertNotNull(ex.getMessage());
 417    }
 418   
 419    }
 420   
 421   
 422    // verify that XML 1.2 is not supported
 423  1 public void testXML12() throws IOException {
 424   
 425  1 String data = "<?xml version='1.2'?><root/>";
 426  1 try {
 427  1 builder.build(data, "http://www.example.com");
 428  0 fail("XML 1.2 allowed");
 429    }
 430    catch (ParsingException ex) {
 431  1 assertNotNull(ex.getMessage());
 432    }
 433   
 434    }
 435   
 436   
 437    // verify that XML 2.0 is not supported
 438  1 public void testXML20() throws IOException {
 439   
 440  1 String data = "<?xml version='2.0'?><root/>";
 441  1 try {
 442  1 builder.build(data, "http://www.example.com");
 443  0 fail("XML 2.0 allowed");
 444    }
 445    catch (ParsingException ex) {
 446  1 assertNotNull(ex.getMessage());
 447    }
 448   
 449    }
 450   
 451   
 452  1 public void testIDAttributeType()
 453    throws IOException, ParsingException {
 454   
 455  1 Reader reader = new StringReader(attributeDoc);
 456  1 Document document = builder.build(reader);
 457  1 Element root = document.getRootElement();
 458  1 Attribute att = root.getAttribute("idatt");
 459  1 assertEquals(Attribute.Type.ID, att.getType());
 460  1 assertEquals("p1", att.getValue());
 461   
 462    }
 463   
 464   
 465  1 public void testIDREFAttributeType()
 466    throws IOException, ParsingException {
 467   
 468  1 Reader reader = new StringReader(attributeDoc);
 469  1 Document document = builder.build(reader);
 470  1 Element root = document.getRootElement();
 471  1 Attribute att = root.getAttribute("idrefatt");
 472  1 assertEquals(Attribute.Type.IDREF, att.getType());
 473  1 assertEquals("p1", att.getValue());
 474   
 475    }
 476   
 477   
 478  1 public void testIDREFSAttributeType()
 479    throws IOException, ParsingException {
 480   
 481  1 Reader reader = new StringReader(attributeDoc);
 482  1 Document document = builder.build(reader);
 483  1 Element root = document.getRootElement();
 484  1 Attribute att = root.getAttribute("idrefsatt");
 485  1 assertEquals(Attribute.Type.IDREFS, att.getType());
 486  1 assertEquals("p1 p2", att.getValue());
 487   
 488    }
 489   
 490   
 491  1 public void testBuildFromReader()
 492    throws IOException, ParsingException {
 493   
 494  1 Reader reader = new StringReader(source);
 495  1 Document document = builder.build(reader);
 496  1 verify(document);
 497  1 assertEquals("", document.getBaseURI());
 498   
 499    }
 500   
 501   
 502  1 public void testBuildFromReaderWithBase()
 503    throws IOException, ParsingException {
 504   
 505  1 Reader reader = new StringReader(source);
 506  1 Document document = builder.build(reader, base);
 507  1 verify(document);
 508  1 assertEquals(base, document.getBaseURI());
 509   
 510    }
 511   
 512   
 513    private static class NoLocator extends XMLFilterImpl {
 514   
 515  1 public NoLocator(XMLReader reader) {
 516  1 super(reader);
 517    }
 518   
 519  1 public void setDocumentLocator(Locator locator) {}
 520   
 521    }
 522   
 523   
 524  1 public void testBuildWithoutLocator()
 525    throws IOException, ParsingException, SAXException {
 526   
 527  1 XMLReader xerces = XMLReaderFactory.createXMLReader(
 528    "org.apache.xerces.parsers.SAXParser");
 529  1 XMLReader filter = new NoLocator(xerces);
 530   
 531  1 Builder builder = new Builder(filter);
 532  1 Document document = builder.build(source, "http://www.example.org/");
 533  1 verify(document);
 534  1 assertEquals("http://www.example.org/", document.getBaseURI());
 535   
 536    }
 537   
 538   
 539    private static class WeirdAttributeTypes extends XMLFilterImpl {
 540   
 541  1 public WeirdAttributeTypes(XMLReader reader) {
 542  1 super(reader);
 543    }
 544   
 545  1 public void startElement(String uri, String localName,
 546    String qualifiedName, Attributes atts) throws SAXException {
 547   
 548  1 AttributesImpl newAtts = new AttributesImpl(atts);
 549  1 for (int i = 0; i < newAtts.getLength(); i++) {
 550  9 newAtts.setType(i, "WEIRD");
 551    }
 552   
 553  1 super.startElement(uri, localName, qualifiedName, newAtts);
 554   
 555    }
 556   
 557    }
 558   
 559   
 560  1 public void testWeirdAttributeTypes()
 561    throws IOException, ParsingException, SAXException {
 562   
 563  1 XMLReader xerces = XMLReaderFactory.createXMLReader(
 564    "org.apache.xerces.parsers.SAXParser");
 565  1 XMLReader filter = new WeirdAttributeTypes(xerces);
 566   
 567  1 Builder builder = new Builder(filter);
 568  1 Document document = builder.build(attributeDoc, "http://www.example.org/");
 569  1 Element root = document.getRootElement();
 570  1 assertTrue(root.getAttributeCount() > 0);
 571  1 for (int i = 0; i < root.getAttributeCount(); i++) {
 572  9 assertEquals(Attribute.Type.UNDECLARED, root.getAttribute(i).getType());
 573    }
 574   
 575    }
 576   
 577   
 578    // Here we're faking the non-standard behavior of some older parsers
 579    private static class ParenthesizedEnumeratedAttributeTypes extends XMLFilterImpl {
 580   
 581  1 public ParenthesizedEnumeratedAttributeTypes(XMLReader reader) {
 582  1 super(reader);
 583    }
 584   
 585  1 public void startElement(String uri, String localName,
 586    String qualifiedName, Attributes atts) throws SAXException {
 587   
 588  1 AttributesImpl newAtts = new AttributesImpl(atts);
 589  1 for (int i = 0; i < newAtts.getLength(); i++) {
 590  9 newAtts.setType(i, "(test, data, value)");
 591    }
 592   
 593  1 super.startElement(uri, localName, qualifiedName, newAtts);
 594   
 595    }
 596   
 597    }
 598   
 599   
 600  1 public void testParenthesizedEnumeratedAttributeTypes()
 601    throws IOException, ParsingException, SAXException {
 602   
 603  1 XMLReader xerces = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
 604  1 XMLReader filter = new ParenthesizedEnumeratedAttributeTypes(xerces);
 605   
 606  1 Builder builder = new Builder(filter);
 607  1 Document document = builder.build(attributeDoc, "http://www.example.org/");
 608  1 Element root = document.getRootElement();
 609  1 assertTrue(root.getAttributeCount() > 0);
 610  1 for (int i = 0; i < root.getAttributeCount(); i++) {
 611  9 assertEquals(Attribute.Type.ENUMERATION, root.getAttribute(i).getType());
 612    }
 613   
 614    }
 615   
 616   
 617  1 public void testBuildFromInputStreamWithBase()
 618    throws IOException, ParsingException {
 619  1 InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
 620  1 Document document = builder.build(in, base);
 621  1 verify(document);
 622  1 assertEquals(base, document.getBaseURI());
 623    }
 624   
 625   
 626  1 public void testBuildFromInputStreamWithoutBase()
 627    throws IOException, ParsingException {
 628  1 InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
 629  1 Document document = builder.build(in);
 630  1 verify(document);
 631  1 assertEquals("", document.getBaseURI());
 632    }
 633   
 634   
 635  1 public void testBuildFromStringWithBase()
 636    throws IOException, ParsingException {
 637  1 Document document = builder.build(source, base);
 638  1 verify(document);
 639  1 assertEquals(base, document.getBaseURI());
 640    }
 641   
 642   
 643  1 public void testBuildDocumentThatUsesDoubleQuoteNumericCharacterReferenceInEntityDeclaration()
 644    throws IOException, ParsingException {
 645   
 646  1 String data = "<!DOCTYPE doc [\n"
 647    + "<!ELEMENT doc (#PCDATA)>"
 648    + " <!ENTITY e \"&#34;\">\n"
 649    + "]><root />";
 650   
 651  1 Document document = builder.build(data, null);
 652   
 653  1 Document roundtrip = builder.build(document.toXML(), null);
 654  1 assertEquals(document, roundtrip);
 655   
 656    }
 657   
 658   
 659  1 public void testBuildDocumentThatDeclaresStandardEntityReferences()
 660    throws IOException, ParsingException {
 661   
 662  1 String data = "<!DOCTYPE doc [\n"
 663    + "<!ELEMENT doc (#PCDATA)>"
 664    + "<!ENTITY lt \"&#38;#60;\">\n"
 665    + "<!ENTITY gt \"&#62;\">\n"
 666    + "<!ENTITY amp \"&#38;#38;\">\n"
 667    + "<!ENTITY apos \"&#39;\">\n"
 668    + "<!ENTITY quot \"&#34;\">\n"
 669    + "]><root />";
 670   
 671  1 Document document = builder.build(data, null);
 672  1 Document roundtrip = builder.build(document.toXML(), null);
 673  1 assertEquals(document, roundtrip);
 674   
 675    }
 676   
 677   
 678  1 public void testBuildDocumentThatUsesAmpersandNumericCharacterReferenceInEntityDeclaration()
 679    throws IOException, ParsingException {
 680   
 681  1 String data = "<!DOCTYPE doc [\n"
 682    + "<!ELEMENT doc (#PCDATA)>"
 683    + " <!ENTITY e \"&#x26;\">\n"
 684    + "]><root />";
 685   
 686  1 Document document = builder.build(data, null);
 687   
 688  1 Document roundtrip = builder.build(document.toXML(), null);
 689  1 assertEquals(document, roundtrip);
 690   
 691    }
 692   
 693   
 694  1 public void testBuildDocumentThatUsesDoubleQuoteNumericCharacterReferenceInAttributeDeclaration()
 695    throws IOException, ParsingException {
 696   
 697  1 String data = "<!DOCTYPE doc [\n"
 698    + "<!ATTLIST root test (CDATA) \"&#x34;\">\n"
 699    + "]><root />";
 700   
 701  1 Document document = builder.build(data, null);
 702   
 703  1 Document roundtrip = builder.build(document.toXML(), null);
 704  1 assertEquals(document, roundtrip);
 705   
 706    }
 707   
 708   
 709  1 public void testMemoryFreedByBuilder()
 710    throws IOException, ParsingException, InterruptedException {
 711   
 712  1 String data = "<root />";
 713   
 714  1 Document document = builder.build(data, null);
 715  1 WeakReference ref = new WeakReference(document);
 716  1 document = null;
 717  1 System.gc();
 718  1 System.gc();
 719  1 System.gc();
 720  1 Thread.sleep(1000);
 721  1 assertNull(ref.get());
 722   
 723    }
 724   
 725   
 726  1 public void testBuildFromInvalidDoc()
 727    throws IOException, ParsingException {
 728   
 729  1 try {
 730  1 validator.build(source, base);
 731  0 fail("Built invalid doc");
 732    }
 733    catch (ValidityException ex) {
 734  1 Document document = ex.getDocument();
 735    // Can't do a full verify just yet due to bugs in Xerces
 736    // verify(ex.getDocument());
 737  1 assertTrue(document.getChild(1) instanceof ProcessingInstruction);
 738  1 assertTrue(document.getChild(2) instanceof Comment);
 739  1 DocType doctype = document.getDocType();
 740  1 Element root = document.getRootElement();
 741   
 742    // assertEquals(1, root.getAttributeCount());
 743    // assertEquals("value", root.getAttributeValue("name"));
 744  1 assertEquals("test", root.getQualifiedName());
 745  1 assertEquals("test", root.getLocalName());
 746  1 assertEquals("", root.getNamespaceURI());
 747   
 748  1 assertTrue(doctype != null);
 749  1 assertTrue(document.getChild(0) instanceof DocType);
 750  1 assertTrue(document.getChild(4) instanceof Comment);
 751  1 assertTrue(document.getChild(2) instanceof Comment);
 752  1 assertEquals(" test ", document.getChild(2).getValue());
 753  1 assertEquals("epilog", document.getChild(4).getValue());
 754  1 assertTrue(document.getChild(1) instanceof ProcessingInstruction);
 755  1 assertEquals("test", doctype.getRootElementName());
 756  1 assertNull(doctype.getPublicID());
 757  1 assertNull(doctype.getSystemID());
 758   
 759  1 String internalDTDSubset = doctype.getInternalDTDSubset();
 760  1 assertTrue(
 761    internalDTDSubset,
 762    internalDTDSubset.indexOf(elementDeclaration) > 0
 763    );
 764  1 assertTrue(
 765    internalDTDSubset,
 766    internalDTDSubset.indexOf(attributeDeclaration) > 0
 767    );
 768  1 assertTrue(
 769    internalDTDSubset,
 770    internalDTDSubset.indexOf(attributeDeclaration2) > 0
 771    );
 772  1 assertTrue(
 773    internalDTDSubset,
 774    internalDTDSubset.indexOf(internalEntityDeclaration) > 0
 775    );
 776  1 assertTrue(
 777    internalDTDSubset,
 778    internalDTDSubset.indexOf(externalEntityDeclarationPublic) > 0
 779    );
 780  1 assertTrue(
 781    internalDTDSubset,
 782    internalDTDSubset.indexOf(externalEntityDeclarationSystem) > 0
 783    );
 784  1 assertTrue(
 785    internalDTDSubset,
 786    internalDTDSubset.indexOf(unparsedEntityDeclaration) > 0
 787    );
 788  1 assertTrue(
 789    internalDTDSubset,
 790    internalDTDSubset.indexOf(unparsedEntityDeclarationPublic) > 0
 791    );
 792  1 assertTrue(
 793    internalDTDSubset,
 794    internalDTDSubset.indexOf(notationDeclarationPublic) > 0
 795    );
 796  1 assertTrue(
 797    internalDTDSubset,
 798    internalDTDSubset.indexOf(notationDeclarationSystem) > 0
 799    );
 800  1 assertTrue(
 801    internalDTDSubset,
 802    internalDTDSubset.indexOf(notationDeclarationPublicAndSystem) > 0
 803    );
 804   
 805    }
 806   
 807    }
 808   
 809   
 810  1 public void testBuildFromStringWithNullBase()
 811    throws IOException, ParsingException {
 812  1 Document document = builder.build(source, null);
 813  1 verify(document);
 814  1 assertEquals("", document.getBaseURI());
 815    }
 816   
 817   
 818  13 private void verify(Document document) {
 819   
 820  13 assertTrue(document.getChild(1) instanceof ProcessingInstruction);
 821  13 assertTrue(document.getChild(2) instanceof Comment);
 822  13 DocType doctype = document.getDocType();
 823  13 Element root = document.getRootElement();
 824   
 825  13 assertEquals(1, root.getAttributeCount());
 826  13 assertEquals("value", root.getAttributeValue("name"));
 827  13 assertEquals("test", root.getQualifiedName());
 828  13 assertEquals("test", root.getLocalName());
 829  13 assertEquals("", root.getNamespaceURI());
 830   
 831  13 assertTrue(doctype != null);
 832  13 assertTrue(document.getChild(0) instanceof DocType);
 833  13 assertTrue(document.getChild(4) instanceof Comment);
 834  13 assertTrue(document.getChild(2) instanceof Comment);
 835  13 assertEquals(" test ", document.getChild(2).getValue());
 836  13 assertEquals("epilog", document.getChild(4).getValue());
 837  13 assertTrue(document.getChild(1) instanceof ProcessingInstruction);
 838  13 assertEquals("test", doctype.getRootElementName());
 839  13 assertNull(doctype.getPublicID());
 840  13 assertNull(doctype.getSystemID());
 841   
 842  13 String internalDTDSubset = doctype.getInternalDTDSubset();
 843  13 assertTrue(
 844    internalDTDSubset,
 845    internalDTDSubset.indexOf(elementDeclaration) > 0
 846    );
 847  13 assertTrue(
 848    internalDTDSubset,
 849    internalDTDSubset.indexOf(attributeDeclaration) > 0
 850    );
 851  13 assertTrue(
 852    internalDTDSubset,
 853    internalDTDSubset.indexOf(attributeDeclaration2) > 0
 854    );
 855  13 assertTrue(
 856    internalDTDSubset,
 857    internalDTDSubset.indexOf(internalEntityDeclaration) > 0
 858    );
 859  13 assertTrue(
 860    internalDTDSubset,
 861    internalDTDSubset.indexOf(externalEntityDeclarationPublic) > 0
 862    );
 863  13 assertTrue(
 864    internalDTDSubset,
 865    internalDTDSubset.indexOf(externalEntityDeclarationSystem) > 0
 866    );
 867  13 assertTrue(
 868    internalDTDSubset,
 869    internalDTDSubset.indexOf(unparsedEntityDeclaration) > 0
 870    );
 871  13 assertTrue(
 872    internalDTDSubset,
 873    internalDTDSubset.indexOf(unparsedEntityDeclarationPublic) > 0
 874    );
 875  13 assertTrue(
 876    internalDTDSubset,
 877    internalDTDSubset.indexOf(notationDeclarationPublic) > 0
 878    );
 879  13 assertTrue(
 880    internalDTDSubset,
 881    internalDTDSubset.indexOf(notationDeclarationSystem) > 0
 882    );
 883  13 assertTrue(
 884    internalDTDSubset,
 885    internalDTDSubset.indexOf(notationDeclarationPublicAndSystem) > 0
 886    );
 887   
 888    }
 889   
 890   
 891  1 public void testValidateFromReader()
 892    throws IOException, ParsingException {
 893   
 894  1 Reader reader1 = new StringReader(validDoc);
 895  1 Document document1 = validator.build(reader1);
 896  1 assertEquals("", document1.getBaseURI());
 897  1 Reader reader2 = new StringReader(validDoc);
 898  1 Document document2 = builder.build(reader2);
 899  1 assertEquals(document2, document1);
 900   
 901    }
 902   
 903   
 904  1 public void testDocumentWithDefaultNamespaceOnPrefixedElement()
 905    throws IOException, ParsingException {
 906   
 907  1 Reader reader = new StringReader("<pre:root " +
 908    "xmlns='http://www.example.org/' " +
 909    "xmlns:pre='http://www.cafeconleche.org/'/>");
 910  1 Document document = builder.build(reader);
 911  1 Element root = document.getRootElement();
 912  1 assertEquals("http://www.example.org/", root.getNamespaceURI(""));
 913  1 assertEquals("http://www.cafeconleche.org/", root.getNamespaceURI("pre"));
 914  1 assertEquals("http://www.cafeconleche.org/", root.getNamespaceURI());
 915   
 916    }
 917   
 918   
 919  1 public void testValidateFromReaderWithBase()
 920    throws IOException, ParsingException {
 921   
 922  1 Reader reader = new StringReader(validDoc);
 923  1 Document document = validator.build(reader, base);
 924  1 assertEquals(base, document.getBaseURI());
 925  1 Reader reader2 = new StringReader(validDoc);
 926  1 Document document2 = builder.build(reader2);
 927  1 assertEquals(document2, document);
 928   
 929    }
 930   
 931   
 932  1 public void testValidateFromInputStreamWithBase()
 933    throws IOException, ParsingException {
 934   
 935  1 InputStream in = new ByteArrayInputStream(validDoc.getBytes("UTF-8"));
 936  1 Document document = validator.build(in, base);
 937  1 assertEquals(base, document.getBaseURI());
 938  1 Reader reader2 = new StringReader(validDoc);
 939  1 Document document2 = builder.build(reader2);
 940  1 assertEquals(document2, document);
 941   
 942    }
 943   
 944   
 945  1 public void testValidateInSeries()
 946    throws IOException, ParsingException {
 947   
 948  1 try {
 949  1 Reader reader = new StringReader(source);
 950  1 validator.build(reader);
 951  0 fail("Allowed invalid doc");
 952    }
 953    catch (ValidityException success) {
 954  1 assertNotNull(success.getMessage());
 955    }
 956    // now make sure validating a valid document doesn't
 957    // throw an exception
 958  1 InputStream in = new ByteArrayInputStream(validDoc.getBytes("UTF-8"));
 959  1 validator.build(in, base);
 960   
 961    }
 962   
 963   
 964  1 public void testValidateFromInputStreamWithoutBase()
 965    throws IOException, ParsingException {
 966   
 967  1 InputStream in = new ByteArrayInputStream(validDoc.getBytes("UTF-8"));
 968  1 Document document = validator.build(in);
 969  1 assertEquals("", document.getBaseURI());
 970  1 Reader reader2 = new StringReader(validDoc);
 971  1 Document document2 = builder.build(reader2);
 972  1 assertEquals(document2, document);
 973   
 974    }
 975   
 976   
 977  1 public void testValidateFromStringWithBase()
 978    throws IOException, ParsingException {
 979   
 980  1 Document document = validator.build(validDoc, base);
 981  1 assertEquals(base, document.getBaseURI());
 982  1 Reader reader2 = new StringReader(validDoc);
 983  1 Document document2 = builder.build(reader2);
 984  1 assertEquals(document2, document);
 985   
 986    }
 987   
 988   
 989  1 public void testValidateWithCrimson()
 990    throws IOException, ParsingException {
 991   
 992  1 XMLReader crimson;
 993  1 try {
 994  1 crimson = XMLReaderFactory.createXMLReader(
 995    "org.apache.crimson.parser.XMLReaderImpl");
 996    }
 997    catch (SAXException ex) {
 998    // can't test Crimson if you can't load it
 999  0 return;
 1000    }
 1001  1 Builder validator = new Builder(crimson, true);
 1002  1 Document document = validator.build(validDoc, base);
 1003  1 assertEquals(base, document.getBaseURI());
 1004  1 Reader reader2 = new StringReader(validDoc);
 1005  1 Document document2 = builder.build(reader2);
 1006  1 assertEquals(document2, document);
 1007   
 1008    }
 1009   
 1010   
 1011  1 public void testNotationAttributeTypeWithCrimson()
 1012    throws IOException, ParsingException {
 1013   
 1014  1 XMLReader crimson;
 1015  1 try {
 1016  1 crimson = XMLReaderFactory.createXMLReader(
 1017    "org.apache.crimson.parser.XMLReaderImpl");
 1018    }
 1019    catch (SAXException ex) {
 1020    // can't test Crimson if you can't load it
 1021  0 return;
 1022    }
 1023   
 1024  1 String data = " <!DOCTYPE doc [\n"
 1025    + "<!ATTLIST e a NOTATION (n) #IMPLIED>\n"
 1026    + "<!ELEMENT document (e)*>\n"
 1027    + "<!ELEMENT e (#PCDATA)>\n"
 1028    + "<!NOTATION n PUBLIC \"whatever\">"
 1029    + "]><document />";
 1030   
 1031  1 Builder builder = new Builder(crimson);
 1032  1 Document document = builder.build(data, base);
 1033   
 1034  1 String s = document.toXML();
 1035  1 Document roundTrip = builder.build(s, base);
 1036  1 assertEquals(document, roundTrip);
 1037   
 1038    }
 1039   
 1040   
 1041  1 public void testEnumerationAttributeType()
 1042    throws IOException, ParsingException {
 1043   
 1044  1 XMLReader crimson;
 1045  1 try {
 1046  1 crimson = XMLReaderFactory.createXMLReader(
 1047    "org.apache.crimson.parser.XMLReaderImpl");
 1048    }
 1049    catch (SAXException ex) {
 1050    // can't test Crimson if you can't load it
 1051  0 return;
 1052    }
 1053  1 Builder builder = new Builder(crimson, false);
 1054  1 String doc = "<!DOCTYPE root [" +
 1055    "<!ATTLIST root att (yes | no) #IMPLIED>" +
 1056    "]><root att='yes'/>";
 1057  1 Document document = builder.build(doc, base);
 1058  1 Element root = document.getRootElement();
 1059  1 Attribute att = root.getAttribute(0);
 1060  1 assertEquals(Attribute.Type.ENUMERATION, att.getType());
 1061   
 1062    }
 1063   
 1064   
 1065  1 public void testWarningDoesNotStopBuild()
 1066    throws IOException, ParsingException, SAXException {
 1067   
 1068  1 XMLReader xerces;
 1069  1 try {
 1070  1 xerces = XMLReaderFactory.createXMLReader(
 1071    "org.apache.xerces.parsers.SAXParser");
 1072    }
 1073    catch (SAXException ex) {
 1074    // can't test Xerces if you can't load it
 1075  0 return;
 1076    }
 1077    // This document generates a warning due to the duplicate
 1078    // attribute declaration
 1079  1 xerces.setFeature(
 1080    "http://apache.org/xml/features/validation/warn-on-duplicate-attdef",
 1081    true);
 1082  1 Builder builder = new Builder(xerces, true);
 1083  1 Document document = builder.build("<!DOCTYPE root [" +
 1084    "<!ELEMENT root ANY>" +
 1085    "<!ATTLIST root b CDATA #IMPLIED>" +
 1086    "<!ATTLIST root b NMTOKEN #REQUIRED>" +
 1087    "]><root b='test'/>", base);
 1088    // The main test is that the document is built successfully.
 1089  1 assertEquals(2, document.getChildCount());
 1090  1 assertEquals("root", document.getRootElement().getQualifiedName());
 1091   
 1092    }
 1093   
 1094   
 1095    private static class EntitySkipper extends XMLFilterImpl {
 1096   
 1097  1 public EntitySkipper(XMLReader reader) {
 1098  1 super(reader);
 1099    }
 1100   
 1101  1 public void characters(char[] data, int start, int length)
 1102    throws SAXException {
 1103  1 super.skippedEntity("name");
 1104    }
 1105   
 1106    }
 1107   
 1108   
 1109  1 public void testSkippedEntityThrowsParsingException()
 1110    throws IOException, ParsingException, SAXException {
 1111   
 1112  1 XMLReader xerces = XMLReaderFactory.createXMLReader(
 1113    "org.apache.xerces.parsers.SAXParser");
 1114  1 XMLReader filter = new EntitySkipper(xerces);
 1115   
 1116  1 Builder builder = new Builder(filter, true);
 1117  1 try {
 1118  1 builder.build("<root>replace</root>", base);
 1119  0 fail("Allowed skipped entity");
 1120    }
 1121    catch (ParsingException success) {
 1122  1 assertNotNull(success.getMessage());
 1123    }
 1124   
 1125    }
 1126   
 1127   
 1128  1 public void testValidateFromStringWithNullBase()
 1129    throws IOException, ParsingException {
 1130  1 Document document = validator.build(validDoc, null);
 1131  1 assertEquals("", document.getBaseURI());
 1132  1 Reader reader2 = new StringReader(validDoc);
 1133  1 Document document2 = builder.build(reader2);
 1134  1 assertEquals(document2, document);
 1135    }
 1136   
 1137   
 1138  1 public void testCannotBuildNamespaceMalformedDocument()
 1139    throws IOException {
 1140   
 1141  1 try {
 1142  1 builder.build("<root:root/>", null);
 1143  0 fail("Builder allowed undeclared prefix");
 1144    }
 1145    catch (ParsingException success) {
 1146  1 assertNotNull(success.getMessage());
 1147    }
 1148   
 1149    }
 1150   
 1151   
 1152  1 public void testInvalidDocFromReader()
 1153    throws IOException, ParsingException {
 1154   
 1155  1 Reader reader = new StringReader(source);
 1156  1 try {
 1157  1 validator.build(reader);
 1158  0 fail("Allowed invalid doc");
 1159    }
 1160    catch (ValidityException success) {
 1161  1 assertNotNull(success.getMessage());
 1162  1 assertTrue(success.getErrorCount() > 0);
 1163  1 for (int i = 0; i < success.getErrorCount(); i++) {
 1164  8 assertNotNull(success.getValidityError(i));
 1165  8 assertTrue(success.getLineNumber(i) >= -1);
 1166  8 assertTrue(success.getColumnNumber(i) >= -1);
 1167    }
 1168  1 if (!xercesBroken) {
 1169  1 Document doc = builder.build(new StringReader(source));
 1170  1 this.verify(success.getDocument());
 1171  1 assertEquals(doc, success.getDocument());
 1172    }
 1173    }
 1174   
 1175    }
 1176   
 1177   
 1178  1 public void testNamespaceMalformedDocumentWithCrimson()
 1179    throws IOException {
 1180   
 1181  1 StringReader reader = new StringReader("<root:root/>");
 1182  1 XMLReader crimson;
 1183  1 try {
 1184  1 crimson = XMLReaderFactory.createXMLReader(
 1185    "org.apache.crimson.parser.XMLReaderImpl");
 1186    }
 1187    catch (SAXException ex) {
 1188    // No Crimson in classpath; therefore can't test it
 1189  0 return;
 1190    }
 1191  1 Builder builder = new Builder(crimson);
 1192  1 try {
 1193  1 builder.build(reader);
 1194  0 fail("Crimson allowed namespace malformed doc");
 1195    }
 1196    catch (ParsingException success) {
 1197  1 assertNotNull(success.getMessage());
 1198    }
 1199   
 1200    }
 1201   
 1202   
 1203  1 public void testValidateNamespaceMalformedInvalidDocumentWithCrimson()
 1204    throws IOException {
 1205   
 1206  1 StringReader reader = new StringReader("<!DOCTYPE root [" +
 1207    "<!ELEMENT root (a)>\n" +
 1208    "<!ELEMENT a (#PCDATA)> \n" +
 1209    "]>\n" +
 1210    "<root><b:b /></root>");
 1211  1 XMLReader crimson;
 1212  1 try {
 1213  1 crimson = XMLReaderFactory.createXMLReader(
 1214    "org.apache.crimson.parser.XMLReaderImpl");
 1215    }
 1216    catch (SAXException ex) {
 1217    // No Crimson in classpath; therefore can't test it
 1218  0 return;
 1219    }
 1220  1 Builder builder = new Builder(crimson);
 1221  1 try {
 1222  1 builder.build(reader);
 1223  0 fail("Crimson allowed namespace malformed doc");
 1224    }
 1225    catch (ValidityException ex) {
 1226  0 fail("Crimson should have thrown ParsingException instead");
 1227    }
 1228    catch (ParsingException success) {
 1229  1 assertNotNull(success.getMessage());
 1230    }
 1231   
 1232    }
 1233   
 1234   
 1235  1 public void testInvalidDocFromReaderWithBase()
 1236    throws IOException, ParsingException {
 1237   
 1238  1 Reader reader1 = new StringReader(source);
 1239  1 try {
 1240  1 validator.build(reader1, base);
 1241  0 fail("Allowed invalid doc");
 1242    }
 1243    catch (ValidityException ex) {
 1244  1 assertNotNull(ex.getMessage());
 1245  1 assertEquals(base, ex.getURI());
 1246  1 assertTrue(ex.getErrorCount() > 0);
 1247  1 for (int i = 0; i < ex.getErrorCount(); i++) {
 1248  8 assertNotNull(ex.getValidityError(i));
 1249  8 assertTrue(ex.getLineNumber(i) >= -1);
 1250  8 assertTrue(ex.getColumnNumber(i) >= -1);
 1251    }
 1252  1 if (!xercesBroken) {
 1253  1 Document doc = builder.build(new StringReader(source), base);
 1254  1 this.verify(ex.getDocument());
 1255  1 assertEquals(doc, ex.getDocument());
 1256    }
 1257    }
 1258   
 1259    }
 1260   
 1261   
 1262  1 public void testInvalidDocFromInputStreamWithBase()
 1263    throws IOException, ParsingException {
 1264   
 1265  1 InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
 1266  1 try {
 1267  1 validator.build(in, base);
 1268  0 fail("Allowed invalid doc");
 1269    }
 1270    catch (ValidityException ex) {
 1271  1 assertNotNull(ex.getMessage());
 1272  1 assertEquals(base, ex.getURI());
 1273  1 assertTrue(ex.getErrorCount() > 0);
 1274  1 for (int i = 0; i < ex.getErrorCount(); i++) {
 1275  8 assertNotNull(ex.getValidityError(i));
 1276  8 assertTrue(ex.getLineNumber(i) >= -1);
 1277  8 assertTrue(ex.getColumnNumber(i) >= -1);
 1278    }
 1279  1 if (!xercesBroken) {
 1280  1 Document doc = builder.build(
 1281    new ByteArrayInputStream(source.getBytes("UTF-8")), base
 1282    );
 1283  1 this.verify(ex.getDocument());
 1284  1 assertEquals(doc, ex.getDocument());
 1285    }
 1286    }
 1287   
 1288    }
 1289   
 1290   
 1291  1 public void testInvalidDocFromInputStreamWithoutBase()
 1292    throws IOException, ParsingException {
 1293   
 1294  1 InputStream in = new ByteArrayInputStream(source.getBytes("UTF-8"));
 1295  1 try {
 1296  1 validator.build(in);
 1297  0 fail("Allowed invalid doc");
 1298    }
 1299    catch (ValidityException ex) {
 1300  1 assertNotNull(ex.getMessage());
 1301  1 assertTrue(ex.getErrorCount() > 0);
 1302  1 for (int i = 0; i < ex.getErrorCount(); i++) {
 1303  8 assertNotNull(ex.getValidityError(i));
 1304  8 assertTrue(ex.getLineNumber(i) >= -1);
 1305  8 assertTrue(ex.getColumnNumber(i) >= -1);
 1306    }
 1307  1 if (!xercesBroken) {
 1308  1 Document doc = builder.build(
 1309    new ByteArrayInputStream(source.getBytes("UTF-8"))
 1310    );
 1311  1 this.verify(ex.getDocument());
 1312  1 assertEquals(doc, ex.getDocument());
 1313    }
 1314    }
 1315   
 1316    }
 1317   
 1318   
 1319  1 public void testInvalidDocFromStringWithBase()
 1320    throws IOException, ParsingException {
 1321   
 1322  1 try {
 1323  1 validator.build(source, base);
 1324  0 fail("Allowed invalid doc");
 1325    }
 1326    catch (ValidityException ex) {
 1327  1 assertNotNull(ex.getMessage());
 1328  1 assertEquals(base, ex.getURI());
 1329  1 assertTrue(ex.getErrorCount() > 0);
 1330  1 for (int i = 0; i < ex.getErrorCount(); i++) {
 1331  8 assertNotNull(ex.getValidityError(i));
 1332  8 assertTrue(ex.getLineNumber(i) >= -1);
 1333  8 assertTrue(ex.getColumnNumber(i) >= -1);
 1334    }
 1335  1 if (!xercesBroken) {
 1336  1 Document doc = builder.build(source, base);
 1337  1 this.verify(ex.getDocument());
 1338  1 assertEquals(doc, ex.getDocument());
 1339    }
 1340    }
 1341   
 1342    }
 1343   
 1344   
 1345  1 public void testInvalidDocWithCrimson()
 1346    throws IOException, ParsingException {
 1347   
 1348  1 XMLReader crimson;
 1349  1 try {
 1350  1 crimson = XMLReaderFactory.createXMLReader(
 1351    "org.apache.crimson.parser.XMLReaderImpl");
 1352    }
 1353    catch (SAXException ex) {
 1354    // can't test Crimson if you can't load it
 1355  0 return;
 1356    }
 1357  1 Builder validator = new Builder(crimson, true);
 1358  1 try {
 1359  1 validator.build(source, null);
 1360  0 fail("Allowed invalid doc");
 1361    }
 1362    catch (ValidityException ex) {
 1363  1 assertTrue(ex.getErrorCount() > 0);
 1364  1 assertNull(ex.getURI());
 1365  1 for (int i = 0; i < ex.getErrorCount(); i++) {
 1366  13 assertNotNull(ex.getValidityError(i));
 1367    }
 1368    }
 1369   
 1370    }
 1371   
 1372   
 1373  1 public void testInvalidDocFromStringWithNullBase()
 1374    throws IOException, ParsingException {
 1375   
 1376  1 try {
 1377  1 validator.build(source, null);
 1378  0 fail("Allowed invalid doc");
 1379    }
 1380    catch (ValidityException ex) {
 1381  1 assertTrue(ex.getErrorCount() > 0);
 1382  1 assertNull(ex.getURI());
 1383  1 for (int i = 0; i < ex.getErrorCount(); i++) {
 1384  8 assertNotNull(ex.getValidityError(i));
 1385    }
 1386  1 if (!xercesBroken) {
 1387  1 Document doc = builder.build(source, null);
 1388  1 this.verify(ex.getDocument());
 1389  1 assertEquals(doc, ex.getDocument());
 1390    }
 1391    }
 1392   
 1393    }
 1394   
 1395   
 1396  1 public void testJavaEncodings()
 1397    throws IOException, ParsingException {
 1398   
 1399  1 String str = "<?xml version='1.0' encoding='ISO8859_1'?>" +
 1400    "<root>é</root>";
 1401  1 byte[] data = str.getBytes("8859_1");
 1402  1 InputStream in = new ByteArrayInputStream(data);
 1403  1 Document doc = builder.build(in);
 1404  1 assertEquals("é", doc.getValue());
 1405   
 1406    }
 1407   
 1408   
 1409    // Crimson improperly converts 0x0D and 0x0A to spaces
 1410    // even when the attribute type is not CDATA.
 1411    // This bug explains why the canonicalizer tests fail
 1412    // with Crimson
 1413  1 public void testCrimsonCharacterReferenceBug()
 1414    throws IOException, ParsingException {
 1415   
 1416  1 String data =
 1417    "<!DOCTYPE test [<!ATTLIST test name ID #IMPLIED>]>"
 1418    + "<test name='&#x0D;'/>";
 1419  1 InputStream in = new ByteArrayInputStream(
 1420    data.getBytes("UTF8"));
 1421  1 Document document = builder.build(in, null);
 1422  1 assertEquals("\r",
 1423    document.getRootElement().getAttributeValue("name"));
 1424   
 1425    }
 1426   
 1427   
 1428  1 public void testBaseRelativeResolution()
 1429    throws IOException, ParsingException {
 1430  1 builder.build(new File(inputDir, "baserelative/test.xml"));
 1431    }
 1432   
 1433   
 1434    // make sure transcoders on input are using normalization
 1435    // form C when converting from other encodings
 1436  1 public void testNFC()
 1437    throws IOException, ParsingException {
 1438   
 1439  1 Document doc = builder.build(new File(inputDir, "nfctest.xml"));
 1440  1 Element root = doc.getRootElement();
 1441  1 String s = root.getValue();
 1442  1 assertEquals(1, s.length());
 1443  1 assertEquals(0xE9, s.charAt(0));
 1444   
 1445    }
 1446   
 1447   
 1448    // This tests XOM's workaround for a bug in Crimson, Xerces,
 1449    // and possibly other parsers
 1450  1 public void testBaseRelativeResolutionRemotely()
 1451    throws IOException, ParsingException {
 1452  1 builder.build("http://www.cafeconleche.org");
 1453    }
 1454   
 1455   
 1456  1 public void testExternalEntityResolution()
 1457    throws IOException, ParsingException {
 1458   
 1459  1 File input = new File(inputDir, "entitytest.xml");
 1460  1 Builder builder = new Builder(false);
 1461  1 Document doc = builder.build(input);
 1462  1 Element root = doc.getRootElement();
 1463  1 Element external = root.getFirstChildElement("external");
 1464  1 assertEquals("Hello from an entity!", external.getValue());
 1465   
 1466    }
 1467   
 1468   
 1469    // This test exposes a bug in Crimson but not Xerces.
 1470    // It's testing whether the external DTD subset is read,
 1471    // default attribute values applied, and comments and
 1472    // processing instructions in the external DTD subset are not
 1473    // reported.
 1474  1 public void testExternalDTDSubset()
 1475    throws IOException, ParsingException {
 1476   
 1477  1 File input = new File(inputDir, "externalDTDtest.xml");
 1478  1 Builder builder = new Builder(false);
 1479  1 Document doc = builder.build(input);
 1480  1 assertEquals(2, doc.getChildCount());
 1481  1 Element root = doc.getRootElement();
 1482  1 Attribute name = root.getAttribute("name");
 1483  1 assertEquals("value", name.getValue());
 1484  1 DocType doctype = doc.getDocType();
 1485  1 assertEquals("", doctype.getInternalDTDSubset());
 1486   
 1487    }
 1488   
 1489   
 1490    /* <?xml version="1.0"?>
 1491    <!DOCTYPE root [
 1492    <!ELEMENT root (#PCDATA)>
 1493    <!-- comment -->
 1494    <?target PI data?>
 1495    <!NOTATION JPEG SYSTEM "image/jpeg">
 1496    <!ATTLIST root source ENTITY #REQUIRED>
 1497    <!ENTITY picture SYSTEM "picture.jpg" NDATA JPEG>
 1498    ]>
 1499    <root source="picture">
 1500    This document is intended to test the building of
 1501    various constructs in the internal DTD subset.
 1502    </root>
 1503    */
 1504  1 public void testInternalDTDSubset()
 1505    throws ValidityException, ParsingException, IOException {
 1506   
 1507  1 File input = new File(inputDir, "internaldtdsubsettest.xml");
 1508  1 Builder builder = new Builder(false);
 1509  1 Document doc = builder.build(input);
 1510  1 String internalSubset = doc.getDocType().getInternalDTDSubset();
 1511  1 assertTrue(internalSubset.indexOf("<!-- comment -->") > 0);
 1512  1 assertTrue(internalSubset.indexOf("<?target PI data?>") > 0);
 1513  1 assertTrue(internalSubset.indexOf("<!ELEMENT root (#PCDATA)>") > 0);
 1514  1 assertTrue(internalSubset.indexOf("<!ATTLIST root source ENTITY #REQUIRED>") > 0);
 1515    // some confusion in the parser resolving these as relative URLs.
 1516    // This is in accordance with the SAX spec, see
 1517    // http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html#notationDecl(java.lang.String,%20java.lang.String,%20java.lang.String)
 1518    // but how does it know the notation system ID is really a URL?
 1519  1 assertTrue(internalSubset.indexOf("<!ENTITY picture SYSTEM ") > 0);
 1520  1 assertTrue(internalSubset.indexOf("picture.jpg\" NDATA JPEG>") > 0);
 1521  1 assertTrue(internalSubset.indexOf("<!NOTATION JPEG SYSTEM ") > 0);
 1522  1 assertTrue(internalSubset.indexOf("image/jpeg\">") > 0);
 1523   
 1524    }
 1525   
 1526   
 1527  1 public void testInternalEntityDeclDollarSign()
 1528    throws ValidityException, ParsingException, IOException {
 1529   
 1530  1 String input = "<!DOCTYPE root [<!ENTITY test '$!@#$^'>] ><root />";
 1531  1 Builder builder = new Builder(false);
 1532  1 Document doc = builder.build(input, null);
 1533  1 String internalSubset = doc.getDocType().getInternalDTDSubset();
 1534  1 assertTrue(internalSubset.indexOf("<!ENTITY test \"$!@#$^\">") > 0);
 1535   
 1536    }
 1537   
 1538   
 1539  1 public void testInternalDTDSubset5To9()
 1540    throws ValidityException, ParsingException, IOException {
 1541   
 1542  1 String input = "<!DOCTYPE root [<!ATTLIST root source CDATA '56789'>] ><root />";
 1543  1 Builder builder = new Builder(false);
 1544  1 Document doc = builder.build(input, null);
 1545  1 String internalSubset = doc.getDocType().getInternalDTDSubset();
 1546  1 assertTrue(internalSubset.indexOf("<!ATTLIST root source CDATA \"56789\">") > 0);
 1547   
 1548    }
 1549   
 1550   
 1551  1 public void testInternalDTDSubsetPunctuation()
 1552    throws ValidityException, ParsingException, IOException {
 1553   
 1554  1 String input = "<!DOCTYPE root [<!ATTLIST root source CDATA '+,()!'>] ><root />";
 1555  1 Builder builder = new Builder(false);
 1556  1 Document doc = builder.build(input, null);
 1557  1 String internalSubset = doc.getDocType().getInternalDTDSubset();
 1558  1 assertTrue(internalSubset.indexOf("<!ATTLIST root source CDATA \"+,()!\">") > 0);
 1559   
 1560    }
 1561   
 1562   
 1563    /*<!ELEMENT test (#PCDATA)>
 1564    <!-- comment should not be here -->
 1565    <?processing instruction should not be here?>
 1566    <!ATTLIST test name (CDATA) #FIXED "value">
 1567    <!ATTLIST test name CDATA "value">
 1568    <!ATTLIST root anattribute CDATA #REQUIRED>
 1569    <!ATTLIST root anotherattribute CDATA "value">
 1570    <!ENTITY hatch-pic SYSTEM "http://www.example.com/images/cup.gif" NDATA gif>
 1571    <!ENTITY public-pic PUBLIC "public ID" "http://www.example.com/images/cup.gif" NDATA gif>
 1572    <!ENTITY Pub-Status "This is a pre-release of the specification.">
 1573    <!ENTITY open-hatch PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN" "http://www.textuality.com/boilerplate/OpenHatch.xml">
 1574    <!ENTITY test SYSTEM "http://www.textuality.com/boilerplate/OpenHatch.xml">
 1575    <!NOTATION ISODATE SYSTEM "http://www.iso.ch/cate/d15903.html">
 1576    <!NOTATION DATE PUBLIC "DATE PUBLIC ID" "http://www.iso.ch/cate/d15903.html">
 1577    <!NOTATION gif PUBLIC "-//Textuality//TEXT Standard open-hatch boilerplate//EN"> */
 1578  1 public void testInternalAndExternalDTDSubset()
 1579    throws ValidityException, ParsingException, IOException {
 1580   
 1581  1 File input = new File(inputDir, "internalandexternaldtdsubsettest.xml");
 1582  1 Builder builder = new Builder(false);
 1583  1 Document doc = builder.build(input);
 1584  1 String internalSubset = doc.getDocType().getInternalDTDSubset();
 1585  1 assertTrue(internalSubset.indexOf("<!-- comment -->") > 0);
 1586  1 assertTrue(internalSubset.indexOf("<?target PI data?>") > 0);
 1587  1 assertTrue(internalSubset.indexOf("<!ELEMENT root (#PCDATA)>") > 0);
 1588  1 assertTrue(internalSubset.indexOf("<!ATTLIST root source ENTITY #REQUIRED>") > 0);
 1589  1 assertTrue(internalSubset.indexOf("<!ENTITY picture SYSTEM ") > 0);
 1590  1 assertTrue(internalSubset.indexOf("picture.jpg\" NDATA JPEG>") > 0);
 1591  1 assertTrue(internalSubset.indexOf("<!NOTATION JPEG SYSTEM ") > 0);
 1592  1 assertTrue(internalSubset.indexOf("image/jpeg\">") > 0);
 1593   
 1594  1 assertEquals(-1, internalSubset.indexOf("comment should not be here"));
 1595  1 assertEquals(-1, internalSubset.indexOf("processing instruction should not be here"));
 1596  1 assertEquals(-1, internalSubset.indexOf("anattribute"));
 1597  1 assertEquals(-1, internalSubset.indexOf("anotherattribute"));
 1598  1 assertEquals(-1, internalSubset.indexOf("hatch-pic"));
 1599  1 assertEquals(-1, internalSubset.indexOf("public-pic"));
 1600  1 assertEquals(-1, internalSubset.indexOf("open-hatch"));
 1601  1 assertEquals(-1, internalSubset.indexOf("Pub-Status-pic"));
 1602  1 assertEquals(-1, internalSubset.indexOf("Textuality"));
 1603  1 assertEquals(-1, internalSubset.indexOf("15903"));
 1604   
 1605    }
 1606   
 1607   
 1608  1 public void testInternalAndExternalDTDSubsetWithCrimson()
 1609    throws ValidityException, ParsingException, IOException {
 1610   
 1611  1 XMLReader crimson;
 1612  1 try {
 1613  1 crimson = XMLReaderFactory.createXMLReader(
 1614    "org.apache.crimson.parser.XMLReaderImpl");
 1615    }
 1616    catch (SAXException ex) {
 1617    // can't test Crimson if you can't load it
 1618  0 return;
 1619    }
 1620   
 1621  1 Builder builder = new Builder(crimson);
 1622  1 File input = new File(inputDir, "internalandexternaldtdsubsettest.xml");
 1623  1 Document doc = builder.build(input);
 1624  1 String internalSubset = doc.getDocType().getInternalDTDSubset();
 1625  1 assertTrue(internalSubset.indexOf("<!-- comment -->") > 0);
 1626  1 assertTrue(internalSubset.indexOf("<?target PI data?>") > 0);
 1627  1 assertTrue(internalSubset.indexOf("<!ELEMENT root (#PCDATA)>") > 0);
 1628  1 assertTrue(internalSubset.indexOf("<!ATTLIST root source ENTITY #REQUIRED>") > 0);
 1629  1 assertTrue(internalSubset.indexOf("<!ENTITY picture SYSTEM ") > 0);
 1630  1 assertTrue(internalSubset.indexOf("picture.jpg\" NDATA JPEG>") > 0);
 1631  1 assertTrue(internalSubset.indexOf("<!NOTATION JPEG SYSTEM ") > 0);
 1632  1 assertTrue(internalSubset.indexOf("image/jpeg\">") > 0);
 1633   
 1634  1 assertEquals(-1, internalSubset.indexOf("comment should not be here"));
 1635  1 assertEquals(-1, internalSubset.indexOf("processing instruction should not be here"));
 1636  1 assertEquals(-1, internalSubset.indexOf("anattribute"));
 1637  1 assertEquals(-1, internalSubset.indexOf("anotherattribute"));
 1638  1 assertEquals(-1, internalSubset.indexOf("hatch-pic"));
 1639  1 assertEquals(-1, internalSubset.indexOf("public-pic"));
 1640  1 assertEquals(-1, internalSubset.indexOf("open-hatch"));
 1641  1 assertEquals(-1, internalSubset.indexOf("Pub-Status-pic"));
 1642  1 assertEquals(-1, internalSubset.indexOf("Textuality"));
 1643  1 assertEquals(-1, internalSubset.indexOf("15903"));
 1644   
 1645    }
 1646   
 1647   
 1648    // This test exposes a bug in Crimson, Xerces 2.5 and earlier,
 1649    // and possibly other parsers. I've reported the bug in Xerces,
 1650    // and it is fixed in Xerces 2.6.
 1651  1 public void testBaseRelativeResolutionRemotelyWithDirectory()
 1652    throws IOException, ParsingException {
 1653  1 builder.build("http://www.ibiblio.org/xml");
 1654    }
 1655   
 1656   
 1657    // This test exposes a bug in Crimson, Xerces 2.5 and earlier,
 1658    // and possibly other parsers. I've reported the bug in Xerces,
 1659    // and it should be fixed in Xerces 2.6.
 1660  1 public void testRelativeURIResolutionAgainstARedirectedBase()
 1661    throws IOException, ParsingException {
 1662  1 builder.build("http://www.ibiblio.org/xml/redirecttest.xml");
 1663    }
 1664   
 1665   
 1666  1 public void testDontGetNodeFactory() {
 1667   
 1668  1 Builder builder = new Builder();
 1669  1 NodeFactory factory = builder.getNodeFactory();
 1670  1 if (factory != null) {
 1671  0 assertFalse(
 1672    factory.getClass().getName().endsWith("NonVerifyingFactory")
 1673    );
 1674    }
 1675   
 1676    }
 1677   
 1678   
 1679  1 public void testGetNodeFactory() {
 1680  1 NodeFactory factory = new NodeFactory();
 1681  1 Builder builder = new Builder(factory);
 1682  1 assertEquals(factory, builder.getNodeFactory());
 1683    }
 1684   
 1685   
 1686    // Make sure additional namespaces aren't added for
 1687    // attributes. This test is flaky because it assumes
 1688    // the parser reports attributes in the correct order,
 1689    // which is not guaranteed. I use a custom SAX Filter to
 1690    // make sure the namespace declaration comes before the attribute.
 1691  1 public void testAttributesVsNamespaces()
 1692    throws ParsingException, IOException, SAXException {
 1693   
 1694  1 XMLFilter filter = new OrderingFilter();
 1695  1 filter.setParent(
 1696    XMLReaderFactory.createXMLReader(
 1697    "org.apache.xerces.parsers.SAXParser"
 1698    )
 1699    );
 1700  1 Builder builder = new Builder(filter);
 1701  1 String data ="<a/>";
 1702  1 Document doc = builder.build(data, null);
 1703  1 Element root = doc.getRootElement();
 1704  1 root.removeAttribute(root.getAttribute(0));
 1705  1 assertNull(root.getNamespaceURI("pre"));
 1706   
 1707    }
 1708   
 1709   
 1710    private static class OrderingFilter extends XMLFilterImpl {
 1711   
 1712  1 public void startElement(String namespaceURI, String localName,
 1713    String qualifiedName, Attributes atts) throws SAXException {
 1714   
 1715  1 AttributesImpl newAttributes = new AttributesImpl();
 1716  1 newAttributes.addAttribute(
 1717    "",
 1718    "pre",
 1719    "xmlns:pre",
 1720    "CDATA",
 1721    "http://www.example.com/");
 1722  1 newAttributes.addAttribute(
 1723    "http://www.example.com/",
 1724    "name",
 1725    "pre:name",
 1726    "CDATA",
 1727    "value");
 1728  1 super.startElement(namespaceURI, localName, qualifiedName,
 1729    newAttributes);
 1730    }
 1731   
 1732    }
 1733   
 1734   
 1735  1 public void testValidateMalformedDocument()
 1736    throws IOException {
 1737   
 1738  1 Reader reader = new StringReader("<!DOCTYPE root [" +
 1739    "<!ELEMENT root (a, b)>" +
 1740    "<!ELEMENT a (EMPTY)>" +
 1741    "<!ELEMENT b (PCDATA)>" +
 1742    "]><root><a/><b></b>");
 1743  1 try {
 1744  1 validator.build(reader);
 1745  0 fail("Allowed malformed doc");
 1746    }
 1747    catch (ValidityException ex) {
 1748  0 fail("Threw validity error instead of well-formedness error");
 1749    }
 1750    catch (ParsingException ex) {
 1751  1 assertNotNull(ex.getMessage());
 1752  1 assertNull(ex.getURI());
 1753    }
 1754   
 1755    }
 1756   
 1757   
 1758    /* Test for particular bug in Crimson with mixed content declarations */
 1759  1 public void testBuildInternalDTDSubsetWithCrimson()
 1760    throws ParsingException, IOException {
 1761   
 1762  1 String dtd = " <!ELEMENT doc (#PCDATA|a)*>\n";
 1763   
 1764  1 String document = "<!DOCTYPE a [\n" + dtd + "]>\n<a/>";
 1765  1 XMLReader crimson;
 1766  1 try {
 1767  1 crimson = XMLReaderFactory.createXMLReader(
 1768    "org.apache.crimson.parser.XMLReaderImpl");
 1769    }
 1770    catch (SAXException ex) {
 1771    // can't test Crimson if you can't load it
 1772  0 return;
 1773    }
 1774   
 1775  1 Builder builder = new Builder(crimson);
 1776  1 Document doc = builder.build(document, null);
 1777   
 1778  1 String parsedDTD = doc.getDocType().getInternalDTDSubset();
 1779  1 assertEquals(dtd, parsedDTD);
 1780   
 1781    }
 1782   
 1783   
 1784    /* Test for particular bug in Crimson with mixed content declarations */
 1785  1 public void testBuildXMLNamespaceDeclarationWithCrimson()
 1786    throws ParsingException, IOException {
 1787   
 1788  1 String document = "<doc xmlns:xml='http://www.w3.org/XML/1998/namespace' />";
 1789  1 XMLReader crimson;
 1790  1 try {
 1791  1 crimson = XMLReaderFactory.createXMLReader(
 1792    "org.apache.crimson.parser.XMLReaderImpl");
 1793    }
 1794    catch (SAXException ex) {
 1795    // can't test Crimson if you can't load it
 1796  0 return;
 1797    }
 1798   
 1799  1 Builder builder = new Builder(crimson);
 1800  1 Document doc = builder.build(document, null);
 1801   
 1802  1 assertEquals("<doc />", doc.getRootElement().toXML());
 1803   
 1804    }
 1805   
 1806   
 1807  1 public void testBuildIllegalXMLNamespaceDeclarationWithCrimson()
 1808    throws ParsingException, IOException {
 1809   
 1810  1 String document = "<doc xmlns:xml='http://www.w3.org/XML/2005/namespace' />";
 1811  1 XMLReader crimson;
 1812  1 try {
 1813  1 crimson = XMLReaderFactory.createXMLReader(
 1814    "org.apache.crimson.parser.XMLReaderImpl");
 1815    }
 1816    catch (SAXException ex) {
 1817    // can't test Crimson if you can't load it
 1818  0 return;
 1819    }
 1820   
 1821  1 Builder builder = new Builder(crimson);
 1822  1 try {
 1823  1 builder.build(document, null);
 1824  0 fail("Allowed wrong namespace URI for xml prefix");
 1825    }
 1826    catch (ParsingException success) {
 1827  1 assertNotNull(success.getMessage());
 1828    }
 1829   
 1830    }
 1831   
 1832   
 1833  1 public void testATTLISTDeclaresXMLSpacePreserveOnlyWithCrimson()
 1834    throws ParsingException, IOException {
 1835   
 1836  1 String dtd = "<!DOCTYPE a [<!ATTLIST doc xml:space (preserve) 'preserve'>]\n>";
 1837   
 1838  1 String data = dtd + "<doc />";
 1839  1 XMLReader crimson;
 1840  1 try {
 1841  1 crimson = XMLReaderFactory.createXMLReader(
 1842    "org.apache.crimson.parser.XMLReaderImpl");
 1843    }
 1844    catch (SAXException ex) {
 1845    // can't test Crimson if you can't load it
 1846  0 return;
 1847    }
 1848   
 1849  1 Builder builder = new Builder(crimson);
 1850  1 Document doc = builder.build(data, null);
 1851  1 assertEquals(1, doc.getRootElement().getAttributeCount());
 1852   
 1853    }
 1854   
 1855   
 1856  1 public void testNoInternalSubsetWithCrimson()
 1857    throws ParsingException, IOException {
 1858   
 1859  1 XMLReader crimson;
 1860  1 try {
 1861  1 crimson = XMLReaderFactory.createXMLReader(
 1862    "org.apache.crimson.parser.XMLReaderImpl");
 1863    }
 1864    catch (SAXException ex) {
 1865    // can't test Crimson if you can't load it
 1866  0 return;
 1867    }
 1868   
 1869  1 File input = new File(inputDir, "externalDTDtest.xml");
 1870  1 Builder builder = new Builder(crimson);
 1871  1 Document doc = builder.build(input);
 1872  1 String subset = doc.getDocType().getInternalDTDSubset();
 1873  1 assertEquals("", subset);
 1874   
 1875    }
 1876   
 1877   
 1878  1 public void testValidateMalformedDocumentWithCrimson()
 1879    throws IOException {
 1880   
 1881  1 Reader reader = new StringReader("<!DOCTYPE root [" +
 1882    "<!ELEMENT root (a, b)>" +
 1883    "<!ELEMENT a (EMPTY)>" +
 1884    "<!ELEMENT b (PCDATA)>" +
 1885    "]><root><a/><b></b>");
 1886  1 XMLReader crimson;
 1887  1 try {
 1888  1 crimson = XMLReaderFactory.createXMLReader(
 1889    "org.apache.crimson.parser.XMLReaderImpl");
 1890    }
 1891    catch (SAXException ex) {
 1892    // can't test Crimson if you can't load it
 1893  0 return;
 1894    }
 1895  1 Builder validator = new Builder(crimson, true);
 1896  1 try {
 1897  1 validator.build(reader);
 1898  0 fail("Allowed malformed doc");
 1899    }
 1900    catch (ValidityException ex) {
 1901  0 fail("Crimson threw validity error instead of well-formedness error");
 1902    }
 1903    catch (ParsingException success) {
 1904  1 assertNotNull(success.getMessage());
 1905  1 assertNull(success.getURI());
 1906    }
 1907   
 1908    }
 1909   
 1910   
 1911    // This is testing a work-around for a Xerces bug
 1912    // http://nagoya.apache.org/bugzilla/show_bug.cgi?id=27583
 1913    // that reports this as an IOException rather than a SAXException
 1914  1 public void testBuildMalformedDocumentWithUnpairedSurrogate()
 1915    throws IOException {
 1916   
 1917  1 String doc = "<doc>A\uD800A</doc>";
 1918  1 try {
 1919  1 builder.build(doc, "http://www.example.com");
 1920  0 fail("Allowed malformed doc");
 1921    }
 1922    catch (ParsingException success) {
 1923  1 assertNotNull(success.getMessage());
 1924  1 assertEquals("http://www.example.com/", success.getURI());
 1925    }
 1926   
 1927    }
 1928   
 1929   
 1930  1 public void testBuildMalformedDocumentWithBadUnicodeData()
 1931    throws IOException {
 1932   
 1933  1 File f = new File(inputDir, "xmlconf");
 1934  1 f = new File(f, "xmltest");
 1935  1 f = new File(f, "not-wf");
 1936  1 f = new File(f, "sa");
 1937  1 f = new File(f, "170.xml");
 1938  1 if (f.exists()) {
 1939  1 try {
 1940  1 builder.build(f);
 1941  0 fail("Allowed malformed doc");
 1942    }
 1943    catch (ParsingException success) {
 1944  1 assertNotNull(success.getMessage());
 1945  1 assertTrue(success.getURI().endsWith(
 1946    "data/xmlconf/xmltest/not-wf/sa/170.xml"));
 1947  1 assertTrue(success.getURI().startsWith("file:/"));
 1948    }
 1949    }
 1950   
 1951    }
 1952   
 1953   
 1954  1 public void testBuildAnotherMalformedDocumentWithBadUnicodeData()
 1955    throws IOException {
 1956   
 1957  1 String filename = "data/oasis/p02fail30.xml";
 1958  1 File f = new File(inputDir, "oasis");
 1959  1 f = new File(f, "p02fail30.xml");
 1960  1 if (f.exists()) {
 1961  0 try {
 1962  0 builder.build(f);
 1963  0 fail("Allowed malformed doc");
 1964    }
 1965    catch (ParsingException success) {
 1966  0 assertNotNull(success.getMessage());
 1967  0 assertTrue(success.getURI().endsWith(filename));
 1968  0 assertTrue(success.getURI().startsWith("file:/"));
 1969    }
 1970    }
 1971   
 1972    }
 1973   
 1974   
 1975  1 public void testBuildMalformedDocumentWithBadParser()
 1976    throws ParsingException, IOException {
 1977   
 1978  1 try {
 1979  1 XMLReader parser = new CustomReader();
 1980  1 Builder builder = new Builder(parser);
 1981  1 builder.build("http://www.example.org/");
 1982  0 fail("built from bad data");
 1983    }
 1984    catch (ParsingException success) {
 1985  1 assertNotNull(success.getMessage());
 1986  1 assertTrue(success.getCause() instanceof WellformednessException);
 1987    }
 1988   
 1989    }
 1990   
 1991   
 1992  1 public void testBuildMalformedDocumentWithCrimson()
 1993    throws IOException {
 1994   
 1995  1 Reader reader = new StringReader("<!DOCTYPE root [" +
 1996    "<!ELEMENT root (a, b)>" +
 1997    "<!ELEMENT a (EMPTY)>" +
 1998    "<!ELEMENT b (PCDATA)>" +
 1999    "]><root><a/><b></b>");
 2000  1 XMLReader crimson;
 2001  1 try {
 2002  1 crimson = XMLReaderFactory.createXMLReader(
 2003    "org.apache.crimson.parser.XMLReaderImpl");
 2004    }
 2005    catch (SAXException ex) {
 2006    // can't test Crimson if you can't load it
 2007  0 return;
 2008    }
 2009  1 Builder builder = new Builder(crimson);
 2010  1 try {
 2011  1 builder.build(reader);
 2012  0 fail("Allowed malformed doc");
 2013    }
 2014    catch (ValidityException ex) {
 2015  0 fail("Crimson threw validity error instead of well-formedness error");
 2016    }
 2017    catch (ParsingException ex) {
 2018  1 assertNotNull(ex.getMessage());
 2019  1 assertNull(ex.getURI());
 2020    }
 2021   
 2022    }
 2023   
 2024   
 2025  1 public void testNestedExceptionWithSAXParseException()
 2026    throws IOException {
 2027   
 2028  1 Reader reader = new StringReader("<root ");
 2029  1 Builder builder = new Builder();
 2030  1 try {
 2031  1 builder.build(reader);
 2032  0 fail("Allowed malformed doc");
 2033    }
 2034    catch (ValidityException ex) {
 2035  0 fail("Parser threw validity error instead of well-formedness error");
 2036    }
 2037    catch (ParsingException ex) {
 2038  1 assertNotNull(ex.getCause());
 2039    }
 2040   
 2041    }
 2042   
 2043   
 2044  1 public void testBuildFunkyNamespacesWithUntrustedParser()
 2045    throws ParsingException, IOException, SAXException {
 2046   
 2047  1 Reader reader = new StringReader(
 2048    "<root xmlns='http://example.org/'>" +
 2049    "<pre:a xmlns:pre='http://www.root.org/' " +
 2050    "xmlns='http://www.red.com'>" +
 2051    "<b/>" +
 2052    "</pre:a></root>");
 2053  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2054    "org.apache.xerces.parsers.SAXParser");
 2055  1 XMLFilter filter = new XMLFilterImpl();
 2056  1 filter.setParent(parser);
 2057  1 Builder builder = new Builder(filter);
 2058  1 Document doc = builder.build(reader);
 2059  1 Element root = doc.getRootElement();
 2060  1 Element prea = (Element) root.getChild(0);
 2061  1 Element b = (Element) prea.getChild(0);
 2062  1 assertEquals("http://www.red.com", b.getNamespaceURI());
 2063   
 2064    }
 2065   
 2066   
 2067    // from XML Conformance Test Suite; James Clark test
 2068    // valid 097
 2069  1 public void testLineBreaksInInternalDTDSubset()
 2070    throws ParsingException, IOException {
 2071   
 2072  1 Document doc = builder.build(new File(inputDir, "097.xml"));
 2073  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2074    + "<!DOCTYPE doc [\n"
 2075    + " <!ELEMENT doc (#PCDATA)>\n"
 2076    + " <!ENTITY % e SYSTEM \"097.ent\">\n"
 2077    + " <!ATTLIST doc a1 CDATA \"v1\">\n"
 2078    + " <!ATTLIST doc a2 CDATA #IMPLIED>\n"
 2079    + "]>\n"
 2080    + "<doc a1=\"v1\" />\n";
 2081  1 String actual = doc.toXML();
 2082  1 assertEquals(expectedResult, actual);
 2083   
 2084    }
 2085   
 2086   
 2087  1 public void testBuildDocumentThatUndeclaresDefaultNamespace()
 2088    throws ParsingException, IOException {
 2089   
 2090  1 Document doc = builder.build(new File(inputDir, "undeclare.xml"));
 2091  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2092    + "<root xmlns=\"http://www.example.org\" "
 2093    + "xmlns:pre=\"http://www.red.com/\" test=\"test\" "
 2094    + "pre:red=\"value\">some data<something xmlns=\"\" />"
 2095    + "</root>\n";
 2096  1 String actual = doc.toXML();
 2097  1 assertEquals(expectedResult, actual);
 2098   
 2099    }
 2100   
 2101   
 2102  1 public void testBuildFromFileThatContainsNonASCIICharacterInName()
 2103    throws ParsingException, IOException {
 2104   
 2105  1 File f = new File(inputDir, "resumé.xml");
 2106  1 try {
 2107  1 Writer out = new OutputStreamWriter(
 2108    new FileOutputStream(f), "UTF8");
 2109  1 out.write("<resumé />");
 2110  1 out.flush();
 2111  1 out.close();
 2112  1 Document doc = builder.build(f);
 2113  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2114    + "<resumé />\n";
 2115  1 String actual = doc.toXML();
 2116  1 assertEquals(expectedResult, actual);
 2117  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2118  1 assertTrue(doc.getBaseURI().endsWith("data/resum%C3%A9.xml"));
 2119    }
 2120    finally {
 2121  1 if (f.exists()) f.delete();
 2122    }
 2123   
 2124    }
 2125   
 2126   
 2127    // This test fails on Mac OS X. It passes on Linux.
 2128  1 public void testBuildFromFileThatContainsPlane1CharacterInName()
 2129    throws ParsingException, IOException {
 2130   
 2131  1 int gclef = 0x1D120;
 2132  1 char high = (char) ((gclef - 0x10000)/0x400 + 0xD800);
 2133  1 char low = (char) ((gclef - 0x10000) % 0x400 + 0xDC00);
 2134  1 File f = new File(inputDir, "music" + high + "" + low + ".xml");
 2135  1 try {
 2136  1 Writer out = new OutputStreamWriter(
 2137    new FileOutputStream(f), "UTF8");
 2138  0 out.write("<resumé />");
 2139  0 out.flush();
 2140  0 out.close();
 2141  0 Document doc = builder.build(f);
 2142  0 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2143    + "<resumé />\n";
 2144  0 String actual = doc.toXML();
 2145  0 assertEquals(expectedResult, actual);
 2146    }
 2147    finally {
 2148  0 if (f.exists()) f.delete();
 2149    }
 2150   
 2151    }
 2152   
 2153   
 2154  10 private File makeFile(String name) throws IOException {
 2155   
 2156  10 File f = new File(inputDir, "" + name);
 2157  10 Writer out = new OutputStreamWriter(
 2158    new FileOutputStream(f), "UTF8");
 2159  10 out.write("<data/>");
 2160  10 out.flush();
 2161  10 out.close();
 2162  10 return f;
 2163   
 2164    }
 2165   
 2166   
 2167  1 public void testBuildFromFileThatContainsAmpersandInName()
 2168    throws ParsingException, IOException {
 2169   
 2170  1 Document doc = builder.build(new File(inputDir, "&file.xml"));
 2171  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2172    + "<data />\n";
 2173  1 String actual = doc.toXML();
 2174  1 assertEquals(expectedResult, actual);
 2175  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2176  1 assertTrue(doc.getBaseURI().endsWith("data/&file.xml"));
 2177   
 2178    }
 2179   
 2180   
 2181  1 public void testBuildFromFileThatContainsSpaceInName()
 2182    throws ParsingException, IOException {
 2183   
 2184  1 File f = makeFile("space file.xml");
 2185  1 Document doc = builder.build(f);
 2186  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2187    + "<data />\n";
 2188  1 String actual = doc.toXML();
 2189  1 f.delete();
 2190  1 assertEquals(expectedResult, actual);
 2191  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2192  1 assertTrue(doc.getBaseURI().endsWith("data/space%"
 2193    + Integer.toHexString(' ') + "file.xml"));
 2194   
 2195    }
 2196   
 2197   
 2198  1 public void testBuildFromFileThatContainsSharpInName()
 2199    throws ParsingException, IOException {
 2200   
 2201  1 File f = new File(inputDir, "#file.xml");
 2202  1 try {
 2203  1 Writer out = new OutputStreamWriter(
 2204    new FileOutputStream(f), "UTF8");
 2205  1 out.write("<data />");
 2206  1 out.flush();
 2207  1 out.close();
 2208  1 Document doc = builder.build(f);
 2209  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2210    + "<data />\n";
 2211  1 String actual = doc.toXML();
 2212  1 assertEquals(expectedResult, actual);
 2213  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2214  1 assertTrue(doc.getBaseURI().endsWith("data/%23file.xml"));
 2215    }
 2216    finally {
 2217  1 if (f.exists()) f.delete();
 2218    }
 2219   
 2220    }
 2221   
 2222   
 2223  1 public void testBuildFromFileThatContainsExclamationPointInName()
 2224    throws ParsingException, IOException {
 2225   
 2226  1 Document doc = builder.build(new File(inputDir, "!file.xml"));
 2227  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2228    + "<data />\n";
 2229  1 String actual = doc.toXML();
 2230  1 assertEquals(expectedResult, actual);
 2231  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2232  1 assertTrue(doc.getBaseURI().endsWith("data/!file.xml"));
 2233   
 2234    }
 2235   
 2236   
 2237  1 public void testBuildFromFileThatContainsDoubleQuoteInName()
 2238    throws ParsingException, IOException {
 2239   
 2240  1 File f = makeFile("\"file\".xml");
 2241  1 try {
 2242  1 Document doc = builder.build(f);
 2243  1 f.delete();
 2244  1 String expectedResult = "<?xml version=\"1.0\"?>\n<data />\n";
 2245  1 String actual = doc.toXML();
 2246  1 assertEquals(expectedResult, actual);
 2247  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2248  1 assertTrue(doc.getBaseURI().endsWith("data/%22file%22.xml"));
 2249    }
 2250    catch (FileNotFoundException ex) {
 2251    // This platform doesn't allow double quotes in file names
 2252    }
 2253   
 2254    }
 2255   
 2256   
 2257  1 public void testBuildFromFileThatContainsSingleQuoteInName()
 2258    throws ParsingException, IOException {
 2259   
 2260  1 File f = makeFile("'file'.xml");
 2261  1 Document doc = builder.build(f);
 2262  1 f.delete();
 2263  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2264    + "<data />\n";
 2265  1 String actual = doc.toXML();
 2266  1 assertEquals(expectedResult, actual);
 2267  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2268  1 assertTrue(doc.getBaseURI().endsWith("data/'file'.xml"));
 2269   
 2270    }
 2271   
 2272   
 2273  1 public void testBuildFromFileThatContainsParenthesesInName()
 2274    throws ParsingException, IOException {
 2275   
 2276  1 Document doc = builder.build(new File(inputDir, "()file.xml"));
 2277  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2278    + "<data />\n";
 2279  1 String actual = doc.toXML();
 2280  1 assertEquals(expectedResult, actual);
 2281  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2282  1 assertTrue(doc.getBaseURI().endsWith("data/()file.xml"));
 2283   
 2284    }
 2285   
 2286   
 2287  1 public void testBuildFromFileThatContainsCurlyBracesInName()
 2288    throws ParsingException, IOException {
 2289   
 2290  1 Document doc = builder.build(new File(inputDir, "{file}.xml"));
 2291  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2292    + "<data />\n";
 2293  1 String actual = doc.toXML();
 2294  1 assertEquals(expectedResult, actual);
 2295  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2296  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2297    + Integer.toHexString('{').toUpperCase() + "file%"
 2298    + Integer.toHexString('}').toUpperCase() + ".xml"));
 2299   
 2300    }
 2301   
 2302   
 2303  1 public void testBuildFromFileThatContainsSquareBracketsInName()
 2304    throws ParsingException, IOException {
 2305   
 2306  1 Document doc = builder.build(new File(inputDir, "[file].xml"));
 2307  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2308    + "<data />\n";
 2309  1 String actual = doc.toXML();
 2310  1 assertEquals(expectedResult, actual);
 2311  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2312  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2313    + Integer.toHexString('[').toUpperCase() + "file%"
 2314    + Integer.toHexString(']').toUpperCase() + ".xml"));
 2315   
 2316    }
 2317   
 2318   
 2319  1 public void testBuildFromFileThatContainsVerticalBarInName()
 2320    throws ParsingException, IOException {
 2321   
 2322  1 File f = makeFile("|file.xml");
 2323  1 try {
 2324  1 Document doc = builder.build(f);
 2325  1 f.delete();
 2326  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2327    + "<data />\n";
 2328  1 String actual = doc.toXML();
 2329  1 assertEquals(expectedResult, actual);
 2330  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2331  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2332    + Integer.toHexString('|').toUpperCase()
 2333    + "file.xml"));
 2334    }
 2335    catch (FileNotFoundException ex) {
 2336    // This platform doesn't allow vertical bars in file names
 2337    }
 2338   
 2339    }
 2340   
 2341   
 2342  1 public void testBuildFromFileThatContainsColonInName()
 2343    throws ParsingException, IOException {
 2344   
 2345  1 File f = makeFile(":file.xml");
 2346  1 try {
 2347  1 Document doc = builder.build(f);
 2348  1 f.delete();
 2349  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2350    + "<data />\n";
 2351  1 String actual = doc.toXML();
 2352  1 assertEquals(expectedResult, actual);
 2353  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2354  1 assertTrue(doc.getBaseURI().endsWith("data/:file.xml"));
 2355    }
 2356    catch (FileNotFoundException ex) {
 2357    // This platform doesn't allow colons in file names
 2358    }
 2359   
 2360    }
 2361   
 2362   
 2363  1 public void testBuildFromFileThatContainsUnderscoreInName()
 2364    throws ParsingException, IOException {
 2365   
 2366  1 File f = makeFile("_file.xml");
 2367  1 Document doc = builder.build(f);
 2368  1 f.delete();
 2369  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2370    + "<data />\n";
 2371  1 String actual = doc.toXML();
 2372  1 assertEquals(expectedResult, actual);
 2373  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2374  1 assertTrue(doc.getBaseURI().endsWith("data/_file.xml"));
 2375   
 2376    }
 2377   
 2378   
 2379  1 public void testBuildFromFileThatContainsUppercaseASCIIInName()
 2380    throws ParsingException, IOException {
 2381   
 2382  1 File f = makeFile("ABCDEFGHIJKLMONPQRSTUVWXYZ.xml");
 2383  1 Document doc = builder.build(f);
 2384  1 f.delete();
 2385  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2386    + "<data />\n";
 2387  1 String actual = doc.toXML();
 2388  1 assertEquals(expectedResult, actual);
 2389  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2390  1 assertTrue(doc.getBaseURI().endsWith("data/ABCDEFGHIJKLMONPQRSTUVWXYZ.xml"));
 2391   
 2392    }
 2393   
 2394   
 2395  1 public void testBuildFromFileThatContainsAsteriskInName()
 2396    throws ParsingException, IOException {
 2397   
 2398  1 File f = makeFile("*file.xml");
 2399  1 try {
 2400  1 Document doc = builder.build(f);
 2401  1 f.delete();
 2402  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2403    + "<data />\n";
 2404  1 String actual = doc.toXML();
 2405  1 assertEquals(expectedResult, actual);
 2406  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2407  1 assertTrue(doc.getBaseURI().endsWith("data/*file.xml"));
 2408    }
 2409    catch (FileNotFoundException ex) {
 2410    // This platform doesn't allow asterisks in file names
 2411    }
 2412   
 2413    }
 2414   
 2415   
 2416  1 public void testBuildFromFileThatContainsSemicolonInName()
 2417    throws ParsingException, IOException {
 2418   
 2419  1 Document doc = builder.build(new File(inputDir, ";file.xml"));
 2420  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2421    + "<data />\n";
 2422  1 String actual = doc.toXML();
 2423  1 assertEquals(expectedResult, actual);
 2424  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2425  1 assertTrue(doc.getBaseURI().endsWith("data/;file.xml"));
 2426   
 2427    }
 2428   
 2429   
 2430  1 public void testBuildFromFileThatContainsPlusSignInName()
 2431    throws ParsingException, IOException {
 2432   
 2433  1 Document doc = builder.build(new File(inputDir, "+file.xml"));
 2434  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2435    + "<data />\n";
 2436  1 String actual = doc.toXML();
 2437  1 assertEquals(expectedResult, actual);
 2438  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2439  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2440    + Integer.toHexString('+').toUpperCase() + "file.xml"));
 2441   
 2442    }
 2443   
 2444   
 2445  1 public void testBuildFromFileThatContainsCommaInName()
 2446    throws ParsingException, IOException {
 2447   
 2448  1 File f = new File(inputDir, ",file.xml");
 2449  1 try {
 2450  1 Writer out = new OutputStreamWriter(
 2451    new FileOutputStream(f), "UTF8");
 2452  1 out.write("<data />");
 2453  1 out.flush();
 2454  1 out.close();
 2455  1 Document doc = builder.build(f);
 2456  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2457    + "<data />\n";
 2458  1 String actual = doc.toXML();
 2459  1 assertEquals(expectedResult, actual);
 2460  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2461  1 assertTrue(doc.getBaseURI().endsWith("data/,file.xml"));
 2462    }
 2463    finally {
 2464  1 if (f.exists()) f.delete();
 2465    }
 2466   
 2467    }
 2468   
 2469   
 2470  1 public void testBuildFromFileThatContainsBackslashInName()
 2471    throws ParsingException, IOException {
 2472   
 2473  1 String os = System.getProperty("os.name", "Unix");
 2474  0 if (os.indexOf("Windows") >= 0) return;
 2475   
 2476  1 File f = new File(inputDir, "\\file.xml");
 2477  1 try {
 2478  1 Writer out = new OutputStreamWriter(
 2479    new FileOutputStream(f), "UTF8");
 2480  1 out.write("<data />");
 2481  1 out.flush();
 2482  1 out.close();
 2483  1 Document doc = builder.build(f);
 2484  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2485    + "<data />\n";
 2486  1 String actual = doc.toXML();
 2487  1 assertEquals(expectedResult, actual);
 2488  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2489  1 assertTrue(doc.getBaseURI().endsWith("data/%5Cfile.xml"));
 2490    }
 2491    finally {
 2492  1 if (f.exists()) f.delete();
 2493    }
 2494   
 2495    }
 2496   
 2497   
 2498  1 public void testBuildFromFileThatContainsC0ControlCharacterInName()
 2499    throws ParsingException, IOException {
 2500   
 2501  1 File f = new File(inputDir, "\u0019file.xml");
 2502  1 try {
 2503  1 Writer out = new OutputStreamWriter(
 2504    new FileOutputStream(f), "UTF8");
 2505  1 out.write("<data />");
 2506  1 out.flush();
 2507  1 out.close();
 2508  1 Document doc = builder.build(f);
 2509  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2510    + "<data />\n";
 2511  1 String actual = doc.toXML();
 2512  1 assertEquals(expectedResult, actual);
 2513  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2514  1 assertTrue(doc.getBaseURI().endsWith("data/%19file.xml"));
 2515    }
 2516    catch (FileNotFoundException ex) {
 2517    // This platform doesn't allow C0 controls in file names
 2518    }
 2519    finally {
 2520  1 if (f.exists()) f.delete();
 2521    }
 2522   
 2523    }
 2524   
 2525   
 2526  1 public void testBuildFromFileThatContainsTabCharacterInName()
 2527    throws ParsingException, IOException {
 2528   
 2529  1 File f = new File(inputDir, "\tfile.xml");
 2530  1 try {
 2531  1 Writer out = new OutputStreamWriter(
 2532    new FileOutputStream(f), "UTF8");
 2533  1 out.write("<data />");
 2534  1 out.flush();
 2535  1 out.close();
 2536  1 Document doc = builder.build(f);
 2537  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2538    + "<data />\n";
 2539  1 String actual = doc.toXML();
 2540  1 assertEquals(expectedResult, actual);
 2541  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2542  1 assertTrue(doc.getBaseURI().endsWith("data/%09file.xml"));
 2543    }
 2544    catch (FileNotFoundException ex) {
 2545    // This platform doesn't allow tabs in file names
 2546    }
 2547    finally {
 2548  1 if (f.exists()) f.delete();
 2549    }
 2550   
 2551    }
 2552   
 2553   
 2554  1 public void testBuildFromFileThatContainsTildeInName()
 2555    throws ParsingException, IOException {
 2556   
 2557  1 File f = new File(inputDir, "~file.xml");
 2558  1 try {
 2559  1 Writer out = new OutputStreamWriter(
 2560    new FileOutputStream(f), "UTF8");
 2561  1 out.write("<data />");
 2562  1 out.flush();
 2563  1 out.close();
 2564  1 Document doc = builder.build(f);
 2565  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2566    + "<data />\n";
 2567  1 String actual = doc.toXML();
 2568  1 assertEquals(expectedResult, actual);
 2569  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2570  1 assertTrue(doc.getBaseURI().endsWith("data/~file.xml"));
 2571    }
 2572    finally {
 2573  1 if (f.exists()) f.delete();
 2574    }
 2575   
 2576    }
 2577   
 2578   
 2579  1 public void testBuildFromFileThatContainsAngleBracketsInName()
 2580    throws ParsingException, IOException {
 2581   
 2582  1 File f = makeFile("<file>.xml");
 2583  1 try {
 2584  1 Document doc = builder.build(f);
 2585  1 f.delete();
 2586  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2587    + "<data />\n";
 2588  1 String actual = doc.toXML();
 2589  1 assertEquals(expectedResult, actual);
 2590  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2591  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2592    + Integer.toHexString('<').toUpperCase() + "file%"
 2593    + Integer.toHexString('>').toUpperCase() + ".xml"));
 2594    }
 2595    catch (FileNotFoundException ex) {
 2596    // This platform doesn't allow < and > in file names
 2597    }
 2598   
 2599    }
 2600   
 2601   
 2602  1 public void testBuildFromFileThatContainsDollarSignInName()
 2603    throws ParsingException, IOException {
 2604   
 2605  1 Document doc = builder.build(new File(inputDir, "$file.xml"));
 2606  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2607    + "<data />\n";
 2608  1 String actual = doc.toXML();
 2609  1 assertEquals(expectedResult, actual);
 2610  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2611  1 assertTrue(doc.getBaseURI().endsWith("data/$file.xml"));
 2612   
 2613    }
 2614   
 2615   
 2616  1 public void testBuildFromFileThatContainsPercentSignInName()
 2617    throws ParsingException, IOException {
 2618   
 2619  1 Document doc = builder.build(new File(inputDir, "%file.xml"));
 2620  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2621    + "<data />\n";
 2622  1 String actual = doc.toXML();
 2623  1 assertEquals(expectedResult, actual);
 2624  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2625  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2626    + Integer.toHexString('%') + "file.xml"));
 2627   
 2628    }
 2629   
 2630   
 2631  1 public void testBuildFromFileThatContainsQuestionMarkInName()
 2632    throws ParsingException, IOException {
 2633   
 2634  1 File f = makeFile("?file.xml");
 2635  1 try {
 2636  1 Document doc = builder.build(f);
 2637  1 f.delete();
 2638  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2639    + "<data />\n";
 2640  1 String actual = doc.toXML();
 2641  1 assertEquals(expectedResult, actual);
 2642  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2643  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2644    + Integer.toHexString('?').toUpperCase() + "file.xml"));
 2645    }
 2646    catch (FileNotFoundException ex) {
 2647    // This platform doesn't allow question marks in file names
 2648    }
 2649   
 2650    }
 2651   
 2652   
 2653  1 public void testBuildFromFileThatContainsAtSignInName()
 2654    throws ParsingException, IOException {
 2655   
 2656  1 Document doc = builder.build(new File(inputDir, "@file.xml"));
 2657  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2658    + "<data />\n";
 2659  1 String actual = doc.toXML();
 2660  1 assertEquals(expectedResult, actual);
 2661  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2662  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2663    + Integer.toHexString('@') + "file.xml"));
 2664   
 2665    }
 2666   
 2667   
 2668  1 public void testBuildFromFileThatContainsEqualsSignInName()
 2669    throws ParsingException, IOException {
 2670   
 2671  1 Document doc = builder.build(new File(inputDir, "=file.xml"));
 2672  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2673    + "<data />\n";
 2674  1 String actual = doc.toXML();
 2675  1 assertEquals(expectedResult, actual);
 2676  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2677  1 assertTrue(doc.getBaseURI().endsWith("data/=file.xml"));
 2678   
 2679    }
 2680   
 2681   
 2682  1 public void testBuildFromFileThatContainsCaretInName()
 2683    throws ParsingException, IOException {
 2684   
 2685  1 Document doc = builder.build(new File(inputDir, "^file.xml"));
 2686  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2687    + "<data />\n";
 2688  1 String actual = doc.toXML();
 2689  1 assertEquals(expectedResult, actual);
 2690  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2691  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2692    + Integer.toHexString('^').toUpperCase() + "file.xml"));
 2693   
 2694    }
 2695   
 2696   
 2697  1 public void testBuildFromFileThatContainsBactickInName()
 2698    throws ParsingException, IOException {
 2699   
 2700  1 Document doc = builder.build(new File(inputDir, "`file.xml"));
 2701  1 String expectedResult = "<?xml version=\"1.0\"?>\n"
 2702    + "<data />\n";
 2703  1 String actual = doc.toXML();
 2704  1 assertEquals(expectedResult, actual);
 2705  1 assertTrue(doc.getBaseURI().startsWith("file:/"));
 2706  1 assertTrue(doc.getBaseURI().endsWith("data/%"
 2707    + Integer.toHexString('`') + "file.xml"));
 2708   
 2709    }
 2710   
 2711   
 2712    private static class NonValidatingFilter extends XMLFilterImpl {
 2713   
 2714  3 public void setFeature(String uri, boolean value)
 2715    throws SAXNotRecognizedException, SAXNotSupportedException {
 2716   
 2717  3 if ("http://xml.org/sax/features/validation".equals(uri) && value) {
 2718  1 throw new SAXNotSupportedException("");
 2719    }
 2720  2 super.setFeature(uri, value);
 2721   
 2722    }
 2723   
 2724  0 public boolean getFeature(String uri)
 2725    throws SAXNotRecognizedException, SAXNotSupportedException {
 2726   
 2727  0 if ("http://xml.org/sax/features/validation".equals(uri)) {
 2728  0 return false;
 2729    }
 2730  0 return super.getFeature(uri);
 2731   
 2732    }
 2733   
 2734   
 2735    }
 2736   
 2737   
 2738  1 public void testNonValidatingParserException() throws SAXException {
 2739   
 2740  1 XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
 2741  1 XMLFilter filter = new NonValidatingFilter();
 2742  1 filter.setParent(parser);
 2743   
 2744  1 try {
 2745  1 new Builder(filter, true, null);
 2746  0 fail("Validating with a non-validating parser");
 2747    }
 2748    catch (XMLException success) {
 2749  1 assertNotNull(success.getMessage());
 2750    }
 2751   
 2752    }
 2753   
 2754    private static class NonEntityResolvingFilter extends XMLFilterImpl {
 2755   
 2756  3 public void setFeature(String uri, boolean value)
 2757    throws SAXNotRecognizedException, SAXNotSupportedException {
 2758   
 2759  3 if (value && (
 2760    "http://xml.org/sax/features/validation".equals(uri)
 2761    || "http://xml.org/sax/features/external-general-entities".equals(uri))
 2762    || "http://xml.org/sax/features/external-parameter-entities".equals(uri)) {
 2763  1 throw new SAXNotSupportedException("");
 2764    }
 2765  2 super.setFeature(uri, value);
 2766   
 2767    }
 2768   
 2769  0 public boolean getFeature(String uri)
 2770    throws SAXNotRecognizedException, SAXNotSupportedException {
 2771   
 2772  0 if ("http://xml.org/sax/features/validation".equals(uri)
 2773    || "http://xml.org/sax/features/external-general-entities".equals(uri)
 2774    || "http://xml.org/sax/features/external-parameter-entities".equals(uri)) {
 2775  0 return false;
 2776    }
 2777  0 return super.getFeature(uri);
 2778   
 2779    }
 2780   
 2781   
 2782    }
 2783   
 2784   
 2785  1 public void testNonEntityResolvingParserException() throws SAXException {
 2786   
 2787  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2788    "org.apache.xerces.parsers.SAXParser");
 2789  1 XMLFilter filter = new NonEntityResolvingFilter();
 2790  1 filter.setParent(parser);
 2791   
 2792  1 try {
 2793  1 new Builder(filter, false, null);
 2794  0 fail("Accepted a non-entity resolving parser");
 2795    }
 2796    catch (XMLException success) {
 2797  1 assertNotNull(success.getMessage());
 2798    }
 2799   
 2800    }
 2801   
 2802   
 2803    // Fake certain errors to test workarounds for bugs in certain
 2804    // parsers, especially Piccolo.
 2805    private static class ExceptionTester extends XMLFilterImpl {
 2806   
 2807    private Exception ex;
 2808   
 2809  8 ExceptionTester(Exception ex) {
 2810  8 this.ex = ex;
 2811    }
 2812   
 2813  8 public void parse(InputSource in) throws IOException, SAXException {
 2814  3 if (ex instanceof IOException) throw (IOException) ex;
 2815  1 else if (ex instanceof SAXException) throw (SAXException) ex;
 2816  4 else throw (RuntimeException) ex;
 2817    }
 2818   
 2819    }
 2820   
 2821   
 2822  1 public void testParserThrowsNullPointerException()
 2823    throws SAXException, IOException {
 2824   
 2825  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2826    "org.apache.xerces.parsers.SAXParser");
 2827  1 Exception cause = new NullPointerException();
 2828  1 XMLFilter filter = new ExceptionTester(cause);
 2829  1 filter.setParent(parser);
 2830  1 Builder builder = new Builder(filter);
 2831   
 2832  1 try {
 2833  1 builder.build("<data/>");
 2834    }
 2835    catch (ParsingException success) {
 2836  1 assertEquals(cause, success.getCause());
 2837    }
 2838   
 2839    }
 2840   
 2841   
 2842  1 public void testParserThrowsNegativeArraySizeException()
 2843    throws SAXException, IOException {
 2844   
 2845  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2846    "org.apache.xerces.parsers.SAXParser");
 2847  1 Exception cause = new NegativeArraySizeException();
 2848  1 XMLFilter filter = new ExceptionTester(cause);
 2849  1 filter.setParent(parser);
 2850  1 Builder builder = new Builder(filter);
 2851   
 2852  1 try {
 2853  1 builder.build("<data/>");
 2854    }
 2855    catch (ParsingException success) {
 2856  1 assertEquals(cause, success.getCause());
 2857    }
 2858   
 2859    }
 2860   
 2861   
 2862  1 public void testParserThrowsArrayIndexOutOfBoundsException()
 2863    throws SAXException, IOException {
 2864   
 2865  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2866    "org.apache.xerces.parsers.SAXParser");
 2867  1 Exception cause = new ArrayIndexOutOfBoundsException();
 2868  1 XMLFilter filter = new ExceptionTester(cause);
 2869  1 filter.setParent(parser);
 2870  1 Builder builder = new Builder(filter);
 2871   
 2872  1 try {
 2873  1 builder.build("<data/>");
 2874    }
 2875    catch (ParsingException success) {
 2876  1 assertEquals(cause, success.getCause());
 2877    }
 2878   
 2879    }
 2880   
 2881   
 2882  1 public void testParserThrowsUTFDataFormatException()
 2883    throws SAXException, IOException {
 2884   
 2885  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2886    "org.apache.xerces.parsers.SAXParser");
 2887  1 Exception cause = new UTFDataFormatException();
 2888  1 XMLFilter filter = new ExceptionTester(cause);
 2889  1 filter.setParent(parser);
 2890  1 Builder builder = new Builder(filter);
 2891   
 2892  1 try {
 2893  1 builder.build("<data/>");
 2894    }
 2895    catch (ParsingException success) {
 2896  1 assertEquals(cause, success.getCause());
 2897    }
 2898   
 2899    }
 2900   
 2901   
 2902  1 public void testCantTurnOffNamespaceHandling()
 2903    throws SAXException, IOException, ParsingException {
 2904   
 2905  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2906    "org.apache.xerces.parsers.SAXParser");
 2907  1 parser.setFeature("http://xml.org/sax/features/namespaces", false);
 2908  1 Builder builder = new Builder(parser);
 2909  1 Document doc = builder.build("<data xmlns='http://www.example.org'/>", null);
 2910  1 assertEquals("http://www.example.org", doc.getRootElement().getNamespaceURI());
 2911   
 2912    }
 2913   
 2914   
 2915  1 public void testParserThrowsCharConversionException()
 2916    throws SAXException, IOException {
 2917   
 2918  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2919    "org.apache.xerces.parsers.SAXParser");
 2920  1 Exception cause = new CharConversionException();
 2921  1 XMLFilter filter = new ExceptionTester(cause);
 2922  1 filter.setParent(parser);
 2923  1 Builder builder = new Builder(filter);
 2924   
 2925  1 try {
 2926  1 builder.build("<data/>");
 2927    }
 2928    catch (ParsingException success) {
 2929  1 assertEquals(cause, success.getCause());
 2930    }
 2931   
 2932    }
 2933   
 2934   
 2935  1 public void testParserThrowsPlainSAXException()
 2936    throws SAXException, IOException {
 2937   
 2938  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2939    "org.apache.xerces.parsers.SAXParser");
 2940  1 Exception cause = new SAXException("What happened to no-args constructor?");
 2941  1 XMLFilter filter = new ExceptionTester(cause);
 2942  1 filter.setParent(parser);
 2943  1 Builder builder = new Builder(filter);
 2944   
 2945  1 try {
 2946  1 builder.build("<data/>");
 2947    }
 2948    catch (ParsingException success) {
 2949  1 assertEquals(cause, success.getCause());
 2950    }
 2951   
 2952    }
 2953   
 2954   
 2955  1 public void testParserThrowsUnexpectedRuntimeException()
 2956    throws SAXException, IOException {
 2957   
 2958  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2959    "org.apache.xerces.parsers.SAXParser");
 2960  1 Exception cause = new RuntimeException();
 2961  1 XMLFilter filter = new ExceptionTester(cause);
 2962  1 filter.setParent(parser);
 2963  1 Builder builder = new Builder(filter);
 2964   
 2965  1 try {
 2966  1 builder.build("<data/>");
 2967    }
 2968    catch (ParsingException success) {
 2969  1 assertEquals(cause, success.getCause());
 2970    }
 2971   
 2972    }
 2973   
 2974   
 2975  1 public void testParserThrowsIOException()
 2976    throws SAXException, ParsingException {
 2977   
 2978  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 2979    "org.apache.xerces.parsers.SAXParser");
 2980  1 Exception cause = new IOException();
 2981  1 XMLFilter filter = new ExceptionTester(cause);
 2982  1 filter.setParent(parser);
 2983  1 Builder builder = new Builder(filter);
 2984   
 2985  1 try {
 2986  1 builder.build("<data/>");
 2987    }
 2988    catch (IOException success) {
 2989  1 assertEquals(cause, success);
 2990    }
 2991   
 2992    }
 2993   
 2994   
 2995  1 public void testCrimsonIgnoresWarning()
 2996    throws SAXException, ParsingException, IOException {
 2997   
 2998   
 2999  1 XMLReader parser;
 3000  1 try {
 3001  1 parser = XMLReaderFactory.createXMLReader(
 3002    "org.apache.crimson.parser.XMLReaderImpl"
 3003    );
 3004    }
 3005    catch (SAXException ex) {
 3006    // Can't test Crimson if you can't load it
 3007  0 return;
 3008    }
 3009  1 XMLFilter filter = new WarningFilter();
 3010  1 filter.setParent(parser);
 3011  1 Builder builder = new Builder(filter);
 3012   
 3013  1 Document doc = builder.build("<data/>", null);
 3014  1 assertEquals("<?xml version=\"1.0\"?>\n<data />\n", doc.toXML());
 3015   
 3016    }
 3017   
 3018   
 3019    private static class WarningFilter extends XMLFilterImpl {
 3020   
 3021  1 public void startElement(String namespaceURI, String localName,
 3022    String qualifiedName, Attributes atts) throws SAXException {
 3023   
 3024  1 this.getErrorHandler().warning(
 3025    new SAXParseException("Warning", new LocatorImpl())
 3026    );
 3027  1 super.startElement(namespaceURI, localName, qualifiedName,
 3028    atts);
 3029   
 3030    }
 3031   
 3032    }
 3033   
 3034   
 3035  1 public void testSaxonsAElfredIsVerified()
 3036    throws SAXException, IOException {
 3037   
 3038  1 XMLReader parser;
 3039  1 try {
 3040  1 parser = XMLReaderFactory.createXMLReader(
 3041    "com.icl.saxon.aelfred.SAXDriver"
 3042    );
 3043    }
 3044    catch (SAXException ex) {
 3045    // Can't test SAXON if you can't load it
 3046  0 return;
 3047    }
 3048  1 Builder builder = new Builder(parser);
 3049   
 3050  1 try {
 3051    // known bug in Saxon; doesn't catch
 3052    // colon in processing instruction targets
 3053  1 builder.build("<?test:data ?><data/>", null);
 3054  0 fail("Didn't verify Saxon's input");
 3055    }
 3056    catch (ParsingException success) {
 3057  1 assertNotNull(success.getMessage());
 3058    }
 3059   
 3060    }
 3061   
 3062   
 3063  1 public void testSaxon7sAElfredIsVerified()
 3064    throws SAXException, IOException {
 3065   
 3066  1 XMLReader parser;
 3067  1 try {
 3068  1 parser = XMLReaderFactory.createXMLReader(
 3069    "net.sf.saxon.aelfred.SAXDriver"
 3070    );
 3071    }
 3072    catch (SAXException ex) {
 3073    // Can't test SAXON if you can't load it
 3074  0 return;
 3075    }
 3076  1 Builder builder = new Builder(parser);
 3077   
 3078  1 try {
 3079    // known bug in Saxon: doesn't catch
 3080    // colon in processing instruction targets
 3081  1 builder.build("<?test:data ?><data/>", null);
 3082  0 fail("Didn't verify Saxon's input");
 3083    }
 3084    catch (ParsingException success) {
 3085  1 assertNotNull(success.getMessage());
 3086    }
 3087   
 3088    }
 3089   
 3090   
 3091  1 public void testGNUJAXPIsVerified()
 3092    throws SAXException, IOException {
 3093   
 3094  1 XMLReader parser;
 3095  1 try {
 3096  1 parser = XMLReaderFactory.createXMLReader(
 3097    "gnu.xml.aelfred2.XmlReader"
 3098    );
 3099    }
 3100    catch (SAXException ex) {
 3101    // Can't test GNU JAXP if you can't load it
 3102  0 return;
 3103    }
 3104  1 Builder builder = new Builder(parser);
 3105   
 3106  1 try {
 3107    // known bug in GNUJAXP: doesn't catch
 3108    // colon in processing instruction targets
 3109  1 builder.build("<?test:data ?><data/>", null);
 3110  0 fail("Didn't verify GNU JAXP's input");
 3111    }
 3112    catch (ParsingException success) {
 3113  1 assertNotNull(success.getMessage());
 3114    }
 3115   
 3116    }
 3117   
 3118   
 3119  1 public void testCatalogOnTopOfTrustedParserIsTrusted() throws
 3120    NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
 3121   
 3122  1 try {
 3123  1 XMLReader parser = XMLReaderFactory.createXMLReader(
 3124    "org.apache.crimson.parser.XMLReaderImpl"
 3125    );
 3126   
 3127  1 Class filter = Class.forName("org.apache.xml.resolver.tools.ResolvingXMLFilter");
 3128  1 Class[] types = {XMLReader.class};
 3129  1 Constructor constructor = filter.getConstructor(types);
 3130  1 Object[] args = {parser};
 3131  1 XMLReader reader = (XMLReader) constructor.newInstance(args);
 3132  1 Builder builder = new Builder(reader);
 3133    // If the factory is a nonverifying factory, then
 3134    // getNodeFactory() won't return it.
 3135  1 assertNull(builder.getNodeFactory());
 3136    }
 3137    catch (ClassNotFoundException ex) {
 3138    // Can't test if we can't find the class
 3139    }
 3140    catch (SAXException ex) {
 3141    // Need a trusted parser to test this
 3142    }
 3143   
 3144    }
 3145   
 3146   
 3147    // XML conformance test case xmlconf/xmltest/valid/not-sa/014.ent
 3148    // shows how this can be necessary. In brief, the internal DTD
 3149    // subset can define or override parameter entities used in the
 3150    // external DTD subset, and that the external DTD subset depends
 3151    // on for well-formedness
 3152  1 public void testPreserveParameterEntitiesInInternalDTDSubset()
 3153    throws ParsingException, IOException {
 3154   
 3155  1 String data = "<!DOCTYPE doc [\n"
 3156    + "<!ENTITY % e 'INCLUDE'>]><doc />";
 3157  1 Document doc = builder.build(data, null);
 3158  1 String subset = doc.getDocType().getInternalDTDSubset();
 3159  1 assertEquals(" <!ENTITY % e \"INCLUDE\">\n", subset);
 3160   
 3161    }
 3162   
 3163   
 3164  1 public void testTrickyCaseFromAppendixA2OfXMLSpec()
 3165    throws ParsingException, IOException {
 3166   
 3167  1 String data = "<?xml version='1.0'?>\n"
 3168    + "<!DOCTYPE test [\n"
 3169    + "<!ELEMENT test (#PCDATA) >\n"
 3170    + "<!ENTITY % xx '&#37;zz;'>\n"
 3171    + "<!ENTITY % zz '&#60;!ENTITY tricky \"error-prone\" >' >\n"
 3172    + "%xx;\n"
 3173    + "]>\n"
 3174    + "<test>This sample shows a &tricky; method.</test>\n";
 3175   
 3176  1 Document doc = builder.build(data, null);
 3177  1 String s = doc.toXML();
 3178  1 Document roundTrip = builder.build(s, null);
 3179  1 assertEquals(doc, roundTrip);
 3180   
 3181    }
 3182   
 3183   
 3184    // This is an example of case where preserving external entity
 3185    // declaration in internal DTD subset is necessary to maintain
 3186    // well-formedness
 3187  1 public void testPreserveExternalGeneralEntityDeclaration()
 3188    throws ParsingException, IOException {
 3189   
 3190  1 Document doc = builder.build(new File(inputDir, "ge.xml"));
 3191  1 DocType doctype = doc.getDocType();
 3192  1 assertEquals(" <!ENTITY ccl SYSTEM \"ge.txt\">\n", doctype.getInternalDTDSubset());
 3193    }
 3194   
 3195   
 3196    // This is an example of case where preserving external entity
 3197    // declaration in internal DTD subset is necessary to maintain
 3198    // validity
 3199  1 public void testPreserveExternalParameterEntityDeclaration()
 3200    throws ParsingException, IOException {
 3201   
 3202  1 Document doc = builder.build(new File(inputDir, "pe.xml"));
 3203  1 DocType doctype = doc.getDocType();
 3204  1 assertEquals(" <!ENTITY % ccl SYSTEM \"pe.txt\">\n", doctype.getInternalDTDSubset());
 3205    }
 3206   
 3207   
 3208  1 public void testNMTOKENSNormalizationOfCarriageReturnLineFeedEntityReferences()
 3209    throws ParsingException, IOException {
 3210   
 3211  1 String data = "<!DOCTYPE attributes [\n"
 3212    + "<!ATTLIST attributes nmtokens NMTOKENS #IMPLIED>]>\n"
 3213    + "<attributes nmtokens = \" this&#x0d;&#x0a; also gets&#x20; normalized \" />";
 3214   
 3215  1 Document doc = builder.build(data, null);
 3216  1 String s = doc.toXML();
 3217  1 Document roundTrip = builder.build(s, null);
 3218  1 assertEquals(doc, roundTrip);
 3219   
 3220    }
 3221   
 3222   
 3223  1 public void testXMLConformanceTestSuiteDocuments()
 3224    throws ParsingException, IOException {
 3225   
 3226  1 File data = new File("data");
 3227  1 File canonical = new File(data, "canonical");
 3228  1 File masterList = new File(canonical, "xmlconf");
 3229  1 masterList = new File(masterList, "xmlconf.xml");
 3230  1 if (masterList.exists()) {
 3231  1 Document xmlconf = builder.build(masterList);
 3232  1 Elements testcases = xmlconf.getRootElement().getChildElements("TESTCASES");
 3233  1 processTestCases(testcases);
 3234    }
 3235   
 3236    }
 3237   
 3238   
 3239    // xmlconf/xmltest/valid/sa/097.xml appears to be screwed up by a lot
 3240    // of parsers
 3241  172 private void processTestCases(Elements testcases)
 3242    throws ParsingException, IOException {
 3243   
 3244  172 for (int i = 0; i < testcases.size(); i++) {
 3245  171 Element testcase = testcases.get(i);
 3246  171 Elements tests = testcase.getChildElements("TEST");
 3247  171 processTests(tests);
 3248  171 Elements level2 = testcase.getChildElements("TESTCASES");
 3249    // need to be recursive to handle recursive IBM test cases
 3250  171 processTestCases(level2);
 3251    }
 3252   
 3253    }
 3254   
 3255   
 3256  171 private void processTests(Elements tests)
 3257    throws ParsingException, IOException {
 3258   
 3259  171 Element parent = new Element("e");
 3260  171 Element child = new Element("a");
 3261  171 parent.appendChild(child);
 3262   
 3263  171 int size = tests.size();
 3264  171 for (int i = 0; i < size; i++) {
 3265  1811 Element test = tests.get(i);
 3266  1811 String namespace = test.getAttributeValue("NAMESPACE");
 3267  4 if ("no".equals(namespace)) continue;
 3268  1807 String type = test.getAttributeValue("TYPE");
 3269  1230 if ("not-wf".equals(type)) continue;
 3270  577 String uri = test.getAttributeValue("URI");
 3271  577 String base = test.getBaseURI();
 3272    // Hack because URIUtil isn't public; and I don't want to
 3273    // depend on 1.4 only java.net.URI
 3274  577 parent.setBaseURI(base);
 3275  577 child.addAttribute(new Attribute("xml:base",
 3276    "http://www.w3.org/XML/1998/namespace", uri));
 3277  577 String resolvedURI = child.getBaseURI();
 3278   
 3279  577 Document doc = builder.build(resolvedURI);
 3280  577 ByteArrayOutputStream out = new ByteArrayOutputStream();
 3281  577 try {
 3282  577 Serializer serializer = new Serializer(out);
 3283  577 serializer.write(doc);
 3284    }
 3285    finally {
 3286  577 out.close();
 3287    }
 3288  577 byte[] actual = out.toByteArray();
 3289   
 3290  577 InputStream in = new ByteArrayInputStream(actual);
 3291  577 try {
 3292  577 Document roundTrip = builder.build(in, resolvedURI);
 3293  577 assertEquals("Failed to roundtrip " + uri, doc, roundTrip);
 3294    }
 3295    catch (ParsingException ex) {
 3296  0 System.out.println(ex.getURI());
 3297  0 System.out.println(doc.toXML());
 3298  0 throw ex;
 3299    }
 3300    finally {
 3301  577 in.close();
 3302    }
 3303    }
 3304   
 3305    }
 3306   
 3307    }