| 1 21 22 package nu.xom.tests; 23 24 import java.io.ByteArrayOutputStream ; 25 import java.io.File ; 26 import java.io.FileNotFoundException ; 27 import java.io.FileOutputStream ; 28 import java.io.IOException ; 29 import java.io.OutputStreamWriter ; 30 import java.io.PrintStream ; 31 import java.io.Reader ; 32 import java.io.StringReader ; 33 import java.io.Writer ; 34 import java.net.URL ; 35 36 import junit.framework.AssertionFailedError; 37 38 import nu.xom.Attribute; 39 import nu.xom.Builder; 40 import nu.xom.Comment; 41 import nu.xom.DocType; 42 import nu.xom.Document; 43 import nu.xom.Element; 44 import nu.xom.Elements; 45 import nu.xom.Node; 46 import nu.xom.NodeFactory; 47 import nu.xom.Nodes; 48 import nu.xom.ParsingException; 49 import nu.xom.Serializer; 50 import nu.xom.Text; 51 52 import nu.xom.xinclude.BadEncodingAttributeException; 53 import nu.xom.xinclude.BadHTTPHeaderException; 54 import nu.xom.xinclude.BadHrefAttributeException; 55 import nu.xom.xinclude.BadParseAttributeException; 56 import nu.xom.xinclude.InclusionLoopException; 57 import nu.xom.xinclude.NoIncludeLocationException; 58 import nu.xom.xinclude.XIncludeException; 59 import nu.xom.xinclude.XIncluder; 60 61 70 public class XIncludeTest extends XOMTestCase { 71 72 private static boolean windows 73 = System.getProperty("os.name", "Unix").indexOf("Windows") >= 0; 74 75 76 public XIncludeTest(String name) { 77 super(name); 78 } 79 80 81 private Builder builder = new Builder(); 82 private File inputDir; 83 private File outputDir; 84 85 private PrintStream systemErr = System.err; 89 90 91 protected void setUp() { 92 93 System.setErr(new PrintStream (new ByteArrayOutputStream ())); 94 95 inputDir = new File ("data"); 96 inputDir = new File (inputDir, "xinclude"); 97 inputDir = new File (inputDir, "input"); 98 99 outputDir = new File ("data"); 100 outputDir = new File (outputDir, "xinclude"); 101 outputDir = new File (outputDir, "output"); 102 103 } 104 105 106 protected void tearDown() { 107 System.setErr(systemErr); 108 } 109 110 111 private void dumpResult(File original, Document result) 112 throws IOException { 113 114 String name = original.getName(); 115 File debug = new File ("data"); 116 debug = new File (debug, "xinclude"); 117 debug = new File (debug, "debug"); 118 File output = new File (debug, name); 119 FileOutputStream out = new FileOutputStream (output); 120 Serializer serializer = new Serializer(out); 121 serializer.write(result); 122 123 } 124 125 126 public void testXPointersResolvedAgainstAcquiredInfoset() 127 throws ParsingException, IOException , XIncludeException { 128 129 File input = new File (inputDir, "tobintop.xml"); 130 Document doc = builder.build(input); 131 Document result = XIncluder.resolve(doc); 132 Document expected = builder.build( 133 new File (outputDir, "tobintop.xml") 134 ); 135 assertEquals(expected, result); 136 137 } 138 139 140 public void testXMLBaseUsedToResolveHref() 141 throws ParsingException, IOException , XIncludeException { 142 143 File input = new File (inputDir, "xmlbasetest.xml"); 144 Document doc = builder.build(input); 145 Document result = XIncluder.resolve(doc); 146 Document expected = builder.build( 147 new File (outputDir, "xmlbasetest.xml") 148 ); 149 assertEquals(expected, result); 150 151 } 152 153 154 public void testResolveThroughXPointer() 158 throws ParsingException, IOException , XIncludeException { 159 160 File input = new File (inputDir, "resolvethruxpointer.xml"); 161 Document doc = builder.build(input); 162 Document result = XIncluder.resolve(doc); 163 Document expectedResult = builder.build( 164 new File (outputDir, "resolvethruxpointer.xml") 165 ); 166 assertEquals(expectedResult, result); 167 168 } 169 170 171 public void testXMLBaseOnIncludeElementUsedToResolveHref() 172 throws ParsingException, IOException , XIncludeException { 173 174 File input = new File (inputDir, "xmlbasetest2.xml"); 175 Document doc = builder.build(input); 176 Document result = XIncluder.resolve(doc); 177 Document expected = builder.build( 178 new File (outputDir, "xmlbasetest2.xml") 179 ); 180 assertEquals(expected, result); 181 182 } 183 184 185 public void testXMLBaseRetainedFromUnincludedElement() 186 throws ParsingException, IOException , XIncludeException { 187 188 File input = new File (inputDir, "xmlbasetest3.xml"); 189 Document doc = builder.build(input); 190 Document result = XIncluder.resolve(doc); 191 Document expected = builder.build( 192 new File (outputDir, "xmlbasetest3.xml") 193 ); 194 assertEquals(expected, result); 195 196 } 197 198 199 public void testMarsh() 200 throws ParsingException, IOException , XIncludeException { 201 202 File input = new File (inputDir, "marshtest.xml"); 203 Document doc = builder.build(input); 204 Document result = XIncluder.resolve(doc); 205 Document expectedResult = builder.build( 206 new File (outputDir, "marshtest.xml") 207 ); 208 assertEquals(expectedResult, result); 209 210 } 211 212 213 public void testIncludeDocumentThatUsesIntradocumentReferences() 214 throws ParsingException, IOException , XIncludeException { 215 216 File input = new File (inputDir, "includedocumentwithintradocumentreferences.xml"); 217 Document doc = builder.build(input); 218 Document result = XIncluder.resolve(doc); 219 Document expectedResult = builder.build( 220 new File (outputDir, "includedocumentwithintradocumentreferences.xml") 221 ); 222 assertEquals(expectedResult, result); 223 224 } 225 226 227 public void testXMLLangAttributes() 228 throws ParsingException, IOException , XIncludeException { 229 230 File input = new File (inputDir, "langtest1.xml"); 231 Document doc = builder.build(input); 232 Document result = XIncluder.resolve(doc); 233 Document expectedResult = builder.build( 234 new File (outputDir, "langtest1.xml") 235 ); 236 assertEquals(expectedResult, result); 237 238 } 239 240 241 public void testInheritedXMLLangAttributes() 242 throws ParsingException, IOException , XIncludeException { 243 244 File input = new File (inputDir, "langtest2.xml"); 245 Document doc = builder.build(input); 246 Document result = XIncluder.resolve(doc); 247 Document expectedResult = builder.build( 248 new File (outputDir, "langtest2.xml") 249 ); 250 assertEquals(expectedResult, result); 251 252 } 253 254 255 public void testNoLanguageSpecified() 256 throws ParsingException, IOException , XIncludeException { 257 258 File input = new File (inputDir, "langtest3.xml"); 259 Document doc = builder.build(input); 260 Document result = XIncluder.resolve(doc); 261 Document expectedResult = builder.build( 262 new File (outputDir, "langtest3.xml") 263 ); 264 assertEquals(expectedResult, result); 265 266 } 267 268 269 public void testXMLBaseNotUsedToResolveMissingHref() 272 throws ParsingException, IOException , XIncludeException { 273 274 File input = new File (inputDir, "marshtestwithxmlbase.xml"); 275 Document doc = builder.build(input); 276 Document result = XIncluder.resolve(doc); 277 Document expectedResult = builder.build( 278 new File (outputDir, "marshtestwithxmlbase.xml") 279 ); 280 assertEquals(expectedResult, result); 281 282 } 283 284 285 public void testEmptyHrefTreatedSameAsMissingHref() 286 throws ParsingException, IOException , XIncludeException { 287 288 File input = new File (inputDir, "marshtestwithxmlbaseandemptyhref.xml"); 289 Document doc = builder.build(input); 290 Document result = XIncluder.resolve(doc); 291 Document expectedResult = builder.build( 292 new File (outputDir, "marshtestwithxmlbase.xml") 293 ); 294 assertEquals(expectedResult, result); 295 296 } 297 298 299 public void testBaselessDocument() 300 throws IOException , ParsingException, XIncludeException { 301 302 Element root = new Element("root"); 303 Element child1 = new Element("xi:include", XIncluder.XINCLUDE_NS); 304 child1.addAttribute(new Attribute("xpointer", "p1")); 305 Element child2 = new Element("child2"); 306 root.appendChild(child1); 307 root.appendChild(child2); 308 child2.addAttribute(new Attribute("id", "p1", Attribute.Type.ID)); 309 Document in = new Document(root); 310 Document out = XIncluder.resolve(in); 311 String result = out.toXML(); 312 assertEquals("<?xml version=\"1.0\"?>\n" + 313 "<root><child2 id=\"p1\" /><child2 id=\"p1\" /></root>\n", result); 314 } 315 316 317 public void testIncludeTextWithCustomNodeFactory() 318 throws ParsingException, IOException , XIncludeException { 319 320 File input = new File (inputDir, "c2.xml"); 321 Builder builder = new Builder(new TextNodeFactory()); 322 Document doc = builder.build(input); 323 Document result = XIncluder.resolve(doc, builder); 324 Document expectedResult = builder.build( 325 new File (outputDir, "c2.xml") 326 ); 327 assertEquals(expectedResult, result); 328 Element root = result.getRootElement(); 329 for (int i = 0; i < root.getChildCount(); i++) { 330 Node node = root.getChild(i); 331 if (node instanceof Text) { 332 assertTrue(node instanceof TextSubclass); 333 } 334 } 335 336 } 337 338 339 public void testParseEqualsTextWithNodeFactoryThatRemovesAllTextNodes() 340 throws ParsingException, IOException , XIncludeException { 341 342 File input = new File (inputDir, "c2.xml"); 343 Document doc = builder.build(input); 344 Document result = XIncluder.resolve(doc, new Builder(new TextFilter())); 345 Document expectedResult = builder.build( 346 new File (outputDir, "c2a.xml") 347 ); 348 assertEquals(expectedResult, result); 349 350 } 351 352 353 private static class TextFilter extends NodeFactory { 354 355 public Nodes makeText(String data) { 356 return new Nodes(); 357 } 358 359 } 360 361 362 public void testParseEqualsTextWithNodeFactoryThatReplacesTextNodesWithComments() 363 throws ParsingException, IOException , XIncludeException { 364 365 File input = new File (inputDir, "c2.xml"); 366 Document doc = builder.build(input); 367 Document result = XIncluder.resolve(doc, new Builder(new TextToComment())); 368 Document expectedResult = builder.build( 369 new File (outputDir, "c2b.xml") 370 ); 371 assertEquals(expectedResult, result); 372 373 } 374 375 376 private static class TextToComment extends NodeFactory { 377 378 public Nodes makeText(String data) { 379 return new Nodes(new Comment(data)); 380 } 381 382 } 383 384 385 public void testParseEqualsTextWithNodeFactoryThatReplacesTextNodesWithAttributes() 386 throws ParsingException, IOException , XIncludeException { 387 388 File input = new File (inputDir, "c2.xml"); 389 Document doc = builder.build(input); 390 Document result = XIncluder.resolve(doc, new Builder(new TextToAttribute())); 391 Document expectedResult = builder.build( 392 new File (outputDir, "c2c.xml") 393 ); 394 assertEquals(expectedResult, result); 395 396 } 397 398 399 public void testParseEqualsTextWithNodeFactoryThatReplacesTextNodesWithTwoElements() 400 throws ParsingException, IOException , XIncludeException { 401 402 File input = new File (inputDir, "c2.xml"); 403 Document doc = builder.build(input); 404 Document result = XIncluder.resolve(doc, new Builder(new TextToElements())); 405 Document expectedResult = builder.build( 406 new File (outputDir, "c2d.xml") 407 ); 408 assertEquals(expectedResult, result); 409 410 } 411 412 413 private static class TextToElements extends NodeFactory { 414 415 public Nodes makeText(String data) { 416 Nodes result = new Nodes(); 417 result.append(new Element("empty1")); 418 result.append(new Element("empty2")); 419 return result; 420 } 421 422 } 423 424 425 private static class TextToAttribute extends NodeFactory { 426 427 public Nodes makeText(String data) { 428 return new Nodes(new Attribute("name", data)); 429 } 430 431 } 432 433 434 public void testUnrecognizedXPointerScheme() 435 throws ParsingException, IOException { 436 437 File input = new File (inputDir, "unrecognizedscheme.xml"); 438 Document doc = builder.build(input); 439 try { 440 XIncluder.resolve(doc); 441 fail("Allowed unrecognized scheme"); 442 } 443 catch (XIncludeException success) { 444 assertNotNull(success.getMessage()); 445 } 446 447 } 448 449 450 public void testUnrecognizedXPointerSchemeWithFallback() 451 throws IOException , ParsingException, XIncludeException { 452 453 File input = new File (inputDir, "unrecognizedschemewithfallback.xml"); 454 File output = new File (outputDir, "unrecognizedschemewithfallback.xml"); 455 Document doc = builder.build(input); 456 Document actual = XIncluder.resolve(doc); 457 Document expected = builder.build(output); 458 assertEquals(expected, actual); 459 460 } 461 462 463 public void testIncludeTextWithCustomNodeFactoryThatChangesElementNames() 464 throws ParsingException, IOException , XIncludeException { 465 466 File input = new File (inputDir, "c1.xml"); 467 Document doc = builder.build(input); 468 Document result = XIncluder.resolve(doc, new Builder(new NodeFactoryTest.CFactory())); 469 Document expectedResult = builder.build( 470 new File (outputDir, "c1a.xml") 471 ); 472 assertEquals(expectedResult, result); 473 474 } 475 476 477 public void testIncludeTextWithCustomNodeFactoryThatOnlyReturnsRoot() 478 throws ParsingException, IOException , XIncludeException { 479 480 File input = new File (inputDir, "c1.xml"); 481 Document doc = builder.build(input); 482 Document result = XIncluder.resolve(doc, new Builder(new NodeFactoryTest.MinimizingFactory())); 483 Document expectedResult = builder.build( 484 new File (outputDir, "c1b.xml") 485 ); 486 assertEquals(expectedResult, result); 487 488 } 489 490 491 public void testIncludeTextWithCustomNodeFactoryThatFiltersElementsNamedB() 492 throws ParsingException, IOException , XIncludeException { 493 494 File input = new File (inputDir, "d1.xml"); 495 Document doc = builder.build(input); 496 Document result = XIncluder.resolve(doc, new Builder(new NodeFactoryTest.BFilter())); 497 Document expectedResult = builder.build( 498 new File (outputDir, "d1.xml") 499 ); 500 assertEquals(expectedResult, result); 501 502 } 503 504 505 public void testIncludeTextWithCustomNodeFactoryThatReturnsEachNonRootElementThreeTimes() 506 throws ParsingException, IOException , XIncludeException { 507 508 File input = new File (inputDir, "c1.xml"); 509 Document doc = builder.build(input); 510 Document result = XIncluder.resolve(doc, 511 new Builder(new NodeFactoryTest.TripleElementFilter())); 512 Document expectedResult = builder.build( 513 new File (outputDir, "triple.xml") 514 ); 515 assertEquals(expectedResult, result); 516 517 } 518 519 520 public void test1() 521 throws ParsingException, IOException , XIncludeException { 522 523 File input = new File (inputDir, "test.xml"); 524 Document doc = builder.build(input); 525 Document result = XIncluder.resolve(doc); 526 Document expectedResult = builder.build( 527 new File (outputDir, "test.xml") 528 ); 529 assertEquals(expectedResult, result); 530 531 } 532 533 534 public void testBaseURIsPreservedInSameDocumentInclusion() 535 throws ParsingException, IOException , XIncludeException { 536 537 File input = new File (inputDir, "includefromsamedocumentwithbase.xml"); 538 Document doc = builder.build(input); 539 Document result = XIncluder.resolve(doc); 540 Document expectedResult = builder.build( 541 new File (outputDir, "includefromsamedocumentwithbase.xml") 542 ); 543 assertEquals(expectedResult, result); 544 545 } 546 547 548 560 561 562 public void testNullBaseURI() 563 throws ParsingException, IOException , XIncludeException { 564 565 File input = new File (inputDir, "disclaimer.xml"); 566 String data = "<document xmlns:xi='http://www.w3.org/2001/XInclude'>" 567 + "\n <p>120 Mz is adequate for an average home user.</p>" 568 + "\n <xi:include HREF='" + input.toURL() + "'/>\n</document>"; 569 Reader reader = new StringReader (data); 570 Document doc = builder.build(reader); 571 Document result = XIncluder.resolve(doc); 572 Document expectedResult = builder.build( 573 new File (outputDir, "c1.xml") 574 ); 575 assertEquals(expectedResult, result); 576 577 } 578 579 580 public void testBadIRIIsAFatalError() 581 throws IOException , ParsingException, XIncludeException { 582 583 String data = "<document xmlns:xi='http://www.w3.org/2001/XInclude'>" 584 + "<xi:include HREF='http://www.example.com/a%5.html'>" 585 + "<xi:fallback>Ooops!</xi:fallback></xi:include></document>"; 586 Reader reader = new StringReader (data); 587 Document doc = builder.build(reader); 588 try { 589 XIncluder.resolve(doc); 590 fail("Resolved fallback when encountering a syntactically incorrect URI"); 591 } 592 catch (BadHrefAttributeException success) { 593 assertNotNull(success.getMessage()); 594 } 595 596 } 597 598 599 public void testBadIRIWithUnrecognizedSchemeIsAFatalError() 600 throws IOException , ParsingException, XIncludeException { 601 602 String data = "<doc xmlns:xi='http://www.w3.org/2001/XInclude'>" 603 + "<xi:include HREF='scheme://www.example.com/a%5.html'>" 604 + "<xi:fallback>Ooops!</xi:fallback></xi:include></doc>"; 605 Reader reader = new StringReader (data); 606 Document doc = builder.build(reader); 607 try { 608 XIncluder.resolve(doc); 609 fail("Resolved fallback when encountering a syntactically incorrect URI"); 610 } 611 catch (BadHrefAttributeException success) { 612 assertNotNull(success.getMessage()); 613 } 614 615 } 616 617 618 public void testGoodIRIWithUnrecognizedSchemeIsAResourceError() 619 throws IOException , ParsingException, XIncludeException { 620 621 String data = "<document xmlns:xi='http://www.w3.org/2001/XInclude'>" 622 + "<xi:include HREF='scheme://www.example.com/a.html'>" 623 + "<xi:fallback>Correct!</xi:fallback></xi:include></document>"; 624 Reader reader = new StringReader (data); 625 Document doc = builder.build(reader); 626 Document result = XIncluder.resolve(doc); 627 assertEquals("<?xml version=\"1.0\"?>\n" 628 + "<document xmlns:xi=\"http://www.w3.org/2001/XInclude\">Correct!</document>\n", 629 result.toXML()); 630 631 } 632 633 634 public void testBadAcceptAttribute() 635 throws ParsingException, IOException , XIncludeException { 636 637 String data = "<document xmlns:xi='http://www.w3.org/2001/XInclude'>" 638 + "\n <p>120 MHz is adequate for an average home user.</p>" 639 + "\n <xi:include HREF='http://www.example.com' " 640 + "accept='text/html
Something: bad'/>\n</document>"; 641 Reader reader = new StringReader (data); 642 Document doc = builder.build(reader); 643 try { 644 XIncluder.resolve(doc); 645 fail("Allowed accept header containing carriage return linefeed"); 646 } 647 catch (BadHTTPHeaderException success) { 648 assertNotNull(success.getMessage()); 649 } 650 651 } 652 653 654 public void testBadAcceptAttributeWithLatin1Character() 655 throws ParsingException, IOException , XIncludeException { 656 657 String data = "<document xmlns:xi='http://www.w3.org/2001/XInclude'>" 658 + "\n <p>120 MHz is adequate for an average home user.</p>" 659 + "\n <xi:include HREF='http://www.example.com' " 660 + "accept='text/html Something: bad'/>\n</document>"; 661 Reader reader = new StringReader (data); 662 Document doc = builder.build(reader); 663 try { 664 XIncluder.resolve(doc); 665 fail("Allowed accept header containing non-ASCII character"); 666 } 667 catch (BadHTTPHeaderException success) { 668 assertNotNull(success.getMessage()); 669 } 670 671 } 672 673 674 public void testUnrecognizedAttributesAreIgnored() 675 throws ParsingException, IOException , XIncludeException { 676 677 File input = new File (inputDir, "extraattributes.xml"); 678 Document doc = builder.build(input); 679 Document result = XIncluder.resolve(doc); 680 Document expectedResult = builder.build( 681 new File (outputDir, "c1.xml") 682 ); 683 assertEquals(expectedResult, result); 684 685 } 686 687 688 public void testEmptyFallback() 689 throws ParsingException, IOException , XIncludeException { 690 691 File input = new File (inputDir, "emptyfallback.xml"); 692 Document doc = builder.build(input); 693 Document result = XIncluder.resolve(doc); 694 Document expectedResult = builder.build( 695 new File (outputDir, "emptyfallback.xml") 696 ); 697 assertEquals(expectedResult, result); 698 699 } 700 701 702 public void testFallbackInIncludedDocument() 703 throws ParsingException, IOException , XIncludeException { 704 705 File input = new File (inputDir, |