1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package catalog; 24 25 import java.io.File; 26 import java.io.FileInputStream; 27 import java.io.IOException; 28 import java.io.InputStream; 29 import java.io.StringReader; 30 import java.io.StringWriter; 31 import java.net.URI; 32 import java.nio.file.Paths; 33 import javax.xml.XMLConstants; 34 import javax.xml.catalog.Catalog; 35 import javax.xml.catalog.CatalogException; 36 import javax.xml.catalog.CatalogFeatures; 37 import javax.xml.catalog.CatalogFeatures.Feature; 38 import javax.xml.catalog.CatalogManager; 39 import javax.xml.catalog.CatalogResolver; 40 import javax.xml.parsers.ParserConfigurationException; 41 import javax.xml.parsers.SAXParser; 42 import javax.xml.parsers.SAXParserFactory; 43 import javax.xml.stream.XMLInputFactory; 44 import javax.xml.stream.XMLStreamConstants; 45 import javax.xml.stream.XMLStreamReader; 46 import javax.xml.transform.Source; 47 import javax.xml.transform.Transformer; 48 import javax.xml.transform.TransformerFactory; 49 import javax.xml.transform.sax.SAXSource; 50 import javax.xml.transform.stream.StreamResult; 51 import javax.xml.transform.stream.StreamSource; 52 import javax.xml.validation.Schema; 53 import javax.xml.validation.SchemaFactory; 54 import javax.xml.validation.Validator; 55 import static jaxp.library.JAXPTestUtilities.clearSystemProperty; 56 import static jaxp.library.JAXPTestUtilities.setSystemProperty; 57 import org.testng.Assert; 58 import org.testng.annotations.BeforeClass; 59 import org.testng.annotations.DataProvider; 60 import org.testng.annotations.Listeners; 61 import org.testng.annotations.Test; 62 import org.xml.sax.Attributes; 63 import org.xml.sax.ErrorHandler; 64 import org.xml.sax.InputSource; 65 import org.xml.sax.SAXException; 66 import org.xml.sax.XMLReader; 67 import org.xml.sax.ext.DefaultHandler2; 68 69 /* 70 * @test 71 * @bug 8081248 8144966 8146606 8146237 8150969 8151162 8152527 8154220 8163232 72 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest 73 * @run testng/othervm -DrunSecMngr=true catalog.CatalogTest 74 * @run testng/othervm catalog.CatalogTest 75 * @summary Tests basic Catalog functions. 76 */ 77 @Listeners({jaxp.library.FilePolicy.class}) 78 public class CatalogTest extends CatalogSupportBase { 79 static final String KEY_FILES = "javax.xml.catalog.files"; 80 81 82 /* 83 * Initializing fields 84 */ 85 @BeforeClass 86 public void setUpClass() throws Exception { 87 super.setUp(); 88 } 89 90 /* 91 * @bug 8162431 92 * Verifies that circular references are caught and 93 * CatalogException is thrown. 94 */ 95 @Test(dataProvider = "getFeatures", expectedExceptions = CatalogException.class) 96 public void testCircularRef(CatalogFeatures cf, String xml) throws Exception { 97 CatalogResolver catalogResolver = CatalogManager.catalogResolver( 98 cf, 99 getClass().getResource(xml).toURI()); 100 catalogResolver.resolve("anyuri", ""); 101 } 102 103 /* 104 DataProvider: used to verify circular reference 105 Data columns: CatalogFeatures, catalog 106 */ 107 @DataProvider(name = "getFeatures") 108 public Object[][] getFeatures() { 109 String self = "catalogReferCircle-itself.xml"; 110 String left = "catalogReferCircle-left.xml"; 111 return new Object[][]{ 112 {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(), self}, 113 {CatalogFeatures.defaults(), self}, 114 {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(), left}, 115 {CatalogFeatures.defaults(), left} 116 }; 117 } 118 119 /* 120 * @bug 8163232 121 * Verifies that the CatalogResolver supports the following XML Resolvers: 122 javax.xml.stream.XMLResolver 123 javax.xml.transform.URIResolver 124 org.w3c.dom.ls.LSResourceResolver 125 org.xml.sax.EntityResolver 126 * 127 * Plus, system and uri entries can equally be used. 128 */ 129 130 /* 131 * Verifies the support for org.xml.sax.EntityResolver. 132 * Expected: the parser returns the expected string. 133 */ 134 @Test(dataProvider = "supportXMLResolver") 135 public void supportEntityResolver(URI catalogFile, String xml, String expected) throws Exception { 136 String xmlSource = getClass().getResource(xml).getFile(); 137 138 CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); 139 MyCatalogHandler handler = new MyCatalogHandler(cr, elementInSystem); 140 SAXParser parser = getSAXParser(false, true, null); 141 parser.parse(xmlSource, handler); 142 143 Assert.assertEquals(handler.getResult().trim(), expected); 144 } 145 146 /* 147 * Verifies the support for javax.xml.stream.XMLResolver. 148 * Expected: the parser returns the expected string. 149 */ 150 @Test(dataProvider = "supportXMLResolver") 151 public void supportXMLResolver(URI catalogFile, String xml, String expected) throws Exception { 152 String xmlSource = getClass().getResource(xml).getFile(); 153 154 CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); 155 156 XMLInputFactory xifactory = XMLInputFactory.newInstance(); 157 xifactory.setProperty(XMLInputFactory.IS_COALESCING, true); 158 xifactory.setProperty(XMLInputFactory.RESOLVER, cr); 159 File file = new File(xmlSource); 160 String systemId = file.toURI().toASCIIString(); 161 InputStream entityxml = new FileInputStream(file); 162 XMLStreamReader streamReader = xifactory.createXMLStreamReader(systemId, entityxml); 163 String result = null; 164 while (streamReader.hasNext()) { 165 int eventType = streamReader.next(); 166 if (eventType == XMLStreamConstants.START_ELEMENT) { 167 eventType = streamReader.next(); 168 if (eventType == XMLStreamConstants.CHARACTERS) { 169 result = streamReader.getText(); 170 } 171 } 172 } 173 System.out.println(": expected [" + expected + "] <> actual [" + result.trim() + "]"); 174 175 Assert.assertEquals(result.trim(), expected); 176 } 177 178 /* 179 * Verifies the support for org.w3c.dom.ls.LSResourceResolver by ShemaFactory. 180 * Success: parsing goes through with no error 181 * Fail: throws Exception if references are not resolved (by the CatalogResolver) 182 */ 183 @Test(dataProvider = "supportLSResourceResolver") 184 public void supportLSResourceResolver(URI catalogFile, Source schemaSource) throws SAXException { 185 186 CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); 187 188 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 189 factory.setResourceResolver(cr); 190 Schema schema = factory.newSchema(schemaSource); 191 192 } 193 194 /* 195 * Verifies the support for org.w3c.dom.ls.LSResourceResolver by Validator. 196 * Success: parsing goes through with no error 197 * Fail: throws Exception if references are not resolved (by the CatalogResolver) 198 */ 199 @Test(dataProvider = "supportLSResourceResolver1") 200 public void supportLSResourceResolver1(URI catalogFile, Source source) throws Exception { 201 202 CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); 203 204 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 205 Validator validator = factory.newSchema().newValidator(); 206 validator.setResourceResolver(cr); 207 validator.validate(source); 208 } 209 210 /* 211 * Verifies the support for javax.xml.transform.URIResolver. 212 * Success: parsing goes through with no error 213 * Fail: throws Exception if references are not resolved (by the CatalogResolver) 214 */ 215 @Test(dataProvider = "supportURIResolver") 216 public void supportURIResolver(URI catalogFile, Source xsl, Source xml, String expected) throws Exception { 217 218 CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); 219 220 TransformerFactory factory = TransformerFactory.newInstance(); 221 factory.setURIResolver(cr); 222 Transformer transformer = factory.newTransformer(xsl); 223 StringWriter out = new StringWriter(); 224 transformer.transform(xml, new StreamResult(out)); 225 if (expected != null) { 226 Assert.assertTrue(out.toString().contains(expected), "supportURIResolver"); 227 } 228 } 229 230 /* 231 DataProvider: used to verify the support of XML Resolvers. 232 Data columns: 233 catalog filepath, xml source file, expected result 234 */ 235 @DataProvider(name = "supportXMLResolver") 236 public Object[][] supportXMLResolver() throws Exception { 237 URI catalogFile = getClass().getResource("catalog.xml").toURI(); 238 URI catalogFileUri = getClass().getResource("catalog_uri.xml").toURI(); 239 240 return new Object[][]{ 241 {catalogFile, "system.xml", "Test system entry"}, 242 {catalogFile, "rewritesystem.xml", "Test rewritesystem entry"}, 243 {catalogFile, "rewritesystem1.xml", "Test rewritesystem entry"}, 244 {catalogFile, "systemsuffix.xml", "Test systemsuffix entry"}, 245 {catalogFile, "delegatesystem.xml", "Test delegatesystem entry"}, 246 {catalogFile, "public.xml", "Test public entry"}, 247 {catalogFile, "delegatepublic.xml", "Test delegatepublic entry"}, 248 // using uri entries 249 {catalogFileUri, "system.xml", "Test system entry"}, 250 {catalogFileUri, "rewritesystem.xml", "Test rewritesystem entry"}, 251 {catalogFileUri, "rewritesystem1.xml", "Test rewritesystem entry"}, 252 {catalogFileUri, "systemsuffix.xml", "Test systemsuffix entry"}, 253 {catalogFileUri, "delegateuri.xml", "Test delegateuri entry"}, 254 {catalogFileUri, "public.xml", "Test public entry"}, 255 }; 256 } 257 258 /* 259 DataProvider: used to verify the support of LSResourceResolver by SchemaFactory. 260 Data columns: 261 catalog filepath, schema source file 262 */ 263 @DataProvider(name = "supportLSResourceResolver") 264 public Object[][] supportLSResourceResolver() throws Exception { 265 URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI(); 266 URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI(); 267 268 /* 269 * XMLSchema.xsd has a reference to XMLSchema.dtd which in turn refers to 270 * datatypes.dtd 271 */ 272 return new Object[][]{ 273 {catalogFile, new StreamSource(new StringReader(xsd_xmlSchema))}, 274 {catalogFile, new StreamSource(new StringReader(xsd_xmlSchema_import))}, 275 {catalogFile, new StreamSource(new StringReader(xsd_include_company))}, 276 {catalogFileUri, new StreamSource(new StringReader(xsd_xmlSchema))}, 277 {catalogFileUri, new StreamSource(new StringReader(xsd_xmlSchema_import))}, 278 {catalogFileUri, new StreamSource(new StringReader(xsd_include_company))}, 279 }; 280 } 281 282 /* 283 DataProvider: used to verify the support of LSResourceResolver by Validator. 284 Data columns: 285 catalog filepath, source file 286 */ 287 @DataProvider(name = "supportLSResourceResolver1") 288 public Object[][] supportLSResourceResolver1() throws Exception { 289 URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI(); 290 URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI(); 291 292 /* 293 * val_test.xml has a reference to system.dtd and val_test.xsd 294 */ 295 SAXSource ss = new SAXSource(new InputSource(xml_val_test)); 296 ss.setSystemId(xml_val_test_id); 297 298 return new Object[][]{ 299 {catalogFile, ss}, 300 {catalogFileUri, ss}, 301 }; 302 } 303 304 305 /* 306 DataProvider: used to verify the support of LSResourceResolver by Validator. 307 Data columns: 308 catalog filepath, xsl source, xml source file 309 */ 310 @DataProvider(name = "supportURIResolver") 311 public Object[][] supportURIResolver() throws Exception { 312 URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI(); 313 URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI(); 314 SAXSource xslSource = new SAXSource(new InputSource(new File(xsl_doc).toURI().toASCIIString())); 315 316 /* 317 * val_test.xml has a reference to system.dtd and val_test.xsd 318 */ 319 SAXSource ss = new SAXSource(new InputSource(xml_val_test)); 320 ss.setSystemId(xml_val_test_id); 321 322 return new Object[][]{ 323 {catalogFile, new SAXSource(new InputSource(new File(xsl_doc).toURI().toASCIIString())), 324 new StreamSource(new File(xml_doc)), "Resolved by a catalog"}, 325 {catalogFileUri, new SAXSource(new InputSource(new StringReader(xsl_include))), 326 new StreamSource(new StringReader(xml_xsl)), null}, 327 }; 328 } 329 330 /* 331 * @bug 8150187 332 * NPE is expected if the systemId is null. The specification for systemId 333 * is as follows: 334 * A system identifier is required on all external entities. XML 335 * requires a system identifier on all external entities, so this value is 336 * always specified. 337 */ 338 @Test(expectedExceptions = NullPointerException.class) 339 public void sysIdCantBeNull() { 340 CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults()); 341 InputSource is = catalogResolver.resolveEntity("-//FOO//DTD XML Dummy V0.0//EN", null); 342 } 343 344 /* 345 * @bug 8156845 346 * Verifies that an URI reference with a urn:publicid is correctly resolved 347 * with an uri entry with a publicId. 348 * 349 * @param expectedFile is not used in this test, it's kept since we're 350 * copying the JCK test and its dataProvider. This test may be reused for 351 * other cases in that test. 352 */ 353 @Test(dataProvider = "resolveUri") 354 public void testMatch1(String cFile, String href, String expectedFile, 355 String expectedUri, String msg) throws Exception { 356 URI catalogFile = getClass().getResource(cFile).toURI(); 357 CatalogResolver cur = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile); 358 Source source = cur.resolve(href, null); 359 Assert.assertNotNull(source, "Source returned is null"); 360 Assert.assertEquals(expectedUri, source.getSystemId(), msg); 361 } 362 363 /* 364 * @bug 8154220 365 * Verifies that the file input is validated properly. Valid input includes 366 * multiple file paths separated by semicolon. 367 */ 368 @Test(dataProvider = "hierarchyOfCatFilesData") 369 public void hierarchyOfCatFiles2(String systemId, String expectedUri) { 370 String file1 = getClass().getResource("first_cat.xml").toExternalForm(); 371 String file2 = getClass().getResource("second_cat.xml").toExternalForm(); 372 String files = file1 + ";" + file2; 373 374 try { 375 setSystemProperty(KEY_FILES, files); 376 CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults()); 377 String sysId = catalogResolver.resolveEntity(null, systemId).getSystemId(); 378 Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"), 379 "System ID match not right"); 380 } finally { 381 clearSystemProperty(KEY_FILES); 382 } 383 384 } 385 386 /* 387 * @bug 8152527 388 * This test is the same as the JDK test ResolveEntityTests:testMatch1. 389 * Verifies that the CatalogResolver resolves a publicId and/or systemId as 390 * expected. 391 */ 392 @Test(dataProvider = "resolveEntity") 393 public void testMatch1(String cfile, String prefer, String sysId, String pubId, 394 String expectedUri, String expectedFile, String msg) throws Exception { 395 URI catalogFile = getClass().getResource(cfile).toURI(); 396 CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build(); 397 CatalogResolver catalogResolver = CatalogManager.catalogResolver(features, catalogFile); 398 InputSource is = catalogResolver.resolveEntity(pubId, sysId); 399 Assert.assertNotNull(is, msg); 400 String expected = (expectedUri == null) ? expectedFile : expectedUri; 401 Assert.assertEquals(expected, is.getSystemId(), msg); 402 } 403 404 /* 405 * @bug 8151162 406 * Verifies that the Catalog matches specified publicId or systemId and returns 407 * results as expected. 408 */ 409 @Test(dataProvider = "matchWithPrefer") 410 public void matchWithPrefer(String prefer, String cfile, String publicId, 411 String systemId, String expected) throws Exception { 412 URI catalogFile = getClass().getResource(cfile).toURI(); 413 Catalog c = CatalogManager.catalog( 414 CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build(), 415 catalogFile); 416 String result; 417 if (publicId != null && publicId.length() > 0) { 418 result = c.matchPublic(publicId); 419 } else { 420 result = c.matchSystem(systemId); 421 } 422 Assert.assertEquals(expected, result); 423 } 424 425 /* 426 * @bug 8151162 427 * Verifies that the CatalogResolver resolves specified publicId or systemId 428 * in accordance with the prefer setting. 429 * prefer "system": resolves with a system entry. 430 * Exception: use the public entry when the catalog contains 431 * only public entry and only publicId is specified. 432 * prefer "public": attempts to resolve with a system entry; 433 * attempts to resolve with a public entry if no matching 434 * system entry is found. 435 */ 436 @Test(dataProvider = "resolveWithPrefer") 437 public void resolveWithPrefer(String prefer, String cfile, String publicId, 438 String systemId, String expected) throws Exception { 439 URI catalogFile = getClass().getResource(cfile).toURI(); 440 CatalogFeatures f = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).with(CatalogFeatures.Feature.RESOLVE, "ignore").build(); 441 CatalogResolver catalogResolver = CatalogManager.catalogResolver(f, catalogFile); 442 String result = catalogResolver.resolveEntity(publicId, systemId).getSystemId(); 443 Assert.assertEquals(expected, result); 444 } 445 446 /** 447 * @bug 8150969 448 * Verifies that the defer attribute set in the catalog file takes precedence 449 * over other settings, in which case, whether next and delegate Catalogs will 450 * be loaded is determined by the defer attribute. 451 */ 452 @Test(dataProvider = "invalidAltCatalogs", expectedExceptions = CatalogException.class) 453 public void testDeferAltCatalogs(String file) throws Exception { 454 URI catalogFile = getClass().getResource(file).toURI(); 455 CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "true").build(); 456 /* 457 Since the defer attribute is set to false in the specified catalog file, 458 the parent catalog will try to load the alt catalog, which will fail 459 since it points to an invalid catalog. 460 */ 461 Catalog catalog = CatalogManager.catalog(features, catalogFile); 462 } 463 464 465 /** 466 * @bug 8146237 467 * PREFER from Features API taking precedence over catalog file 468 */ 469 @Test 470 public void testJDK8146237() throws Exception { 471 URI catalogFile = getClass().getResource("JDK8146237_catalog.xml").toURI(); 472 473 try { 474 CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, "system").build(); 475 Catalog catalog = CatalogManager.catalog(features, catalogFile); 476 CatalogResolver catalogResolver = CatalogManager.catalogResolver(catalog); 477 String actualSystemId = catalogResolver.resolveEntity("-//FOO//DTD XML Dummy V0.0//EN", "http://www.oracle.com/alt1sys.dtd").getSystemId(); 478 Assert.assertTrue(actualSystemId.contains("dummy.dtd"), "Resulting id should contain dummy.dtd, indicating a match by publicId"); 479 480 } catch (Exception e) { 481 Assert.fail(e.getMessage()); 482 } 483 } 484 485 /* 486 @bug 8146606 487 Verifies that the resulting systemId does not contain duplicate slashes 488 */ 489 @Test 490 public void testRewriteSystem() throws Exception { 491 URI catalog = getClass().getResource("rewriteCatalog.xml").toURI(); 492 493 try { 494 CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); 495 String actualSystemId = resolver.resolveEntity(null, "http://remote.com/dtd/book.dtd").getSystemId(); 496 Assert.assertTrue(!actualSystemId.contains("//"), "result contains duplicate slashes"); 497 } catch (Exception e) { 498 Assert.fail(e.getMessage()); 499 } 500 501 } 502 503 /* 504 @bug 8146606 505 Verifies that the resulting systemId does not contain duplicate slashes 506 */ 507 @Test 508 public void testRewriteUri() throws Exception { 509 URI catalog = getClass().getResource("rewriteCatalog.xml").toURI(); 510 511 try { 512 513 CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); 514 String actualSystemId = resolver.resolve("http://remote.com/import/import.xsl", null).getSystemId(); 515 Assert.assertTrue(!actualSystemId.contains("//"), "result contains duplicate slashes"); 516 } catch (Exception e) { 517 Assert.fail(e.getMessage()); 518 } 519 } 520 521 /* 522 @bug 8144966 523 Verifies that passing null as CatalogFeatures will result in a NPE. 524 */ 525 @Test(expectedExceptions = NullPointerException.class) 526 public void testFeatureNull() { 527 CatalogResolver resolver = CatalogManager.catalogResolver(null, null); 528 529 } 530 531 /* 532 @bug 8144966 533 Verifies that passing null as the URI will result in a NPE. 534 */ 535 @Test(expectedExceptions = NullPointerException.class) 536 public void testPathNull() { 537 URI uri = null; 538 CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), uri); 539 } 540 541 /* 542 Tests basic catalog feature by using a CatalogResolver instance to 543 resolve a DTD reference to a locally specified DTD file. If the resolution 544 is successful, the Handler shall return the value of the entity reference 545 that matches the expected value. 546 */ 547 @Test(dataProvider = "catalog") 548 public void testCatalogResolver(String test, String expected, String catalogFile, 549 String xml, SAXParser saxParser) throws Exception { 550 URI catalog = null; 551 if (catalogFile != null) { 552 catalog = getClass().getResource(catalogFile).toURI(); 553 } 554 String url = getClass().getResource(xml).getFile(); 555 try { 556 CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); 557 XMLReader reader = saxParser.getXMLReader(); 558 reader.setEntityResolver(cr); 559 MyHandler handler = new MyHandler(saxParser); 560 reader.setContentHandler(handler); 561 reader.parse(url); 562 System.out.println(test + ": expected [" + expected + "] <> actual [" + handler.getResult() + "]"); 563 Assert.assertEquals(handler.getResult(), expected); 564 } catch (SAXException | IOException e) { 565 Assert.fail(e.getMessage()); 566 } 567 } 568 569 /* 570 Verifies that when there's no match, in this case only an invalid 571 catalog is provided, the resolver will throw an exception by default. 572 */ 573 @Test 574 public void testInvalidCatalog() throws Exception { 575 URI catalog = getClass().getResource("catalog_invalid.xml").toURI(); 576 577 String test = "testInvalidCatalog"; 578 try { 579 CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog); 580 String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId(); 581 } catch (Exception e) { 582 String msg = e.getMessage(); 583 if (msg != null) { 584 if (msg.contains("No match found for publicId")) { 585 Assert.assertEquals(msg, "No match found for publicId 'null' and systemId 'http://remote/xml/dtd/sys/alice/docAlice.dtd'."); 586 System.out.println(test + ": expected [No match found for publicId 'null' and systemId 'http://remote/xml/dtd/sys/alice/docAlice.dtd'.]"); 587 System.out.println("actual [" + msg + "]"); 588 } 589 } 590 } 591 } 592 593 /* 594 Verifies that if resolve is "ignore", an empty InputSource will be returned 595 when there's no match. The systemId is then null. 596 */ 597 @Test 598 public void testIgnoreInvalidCatalog() { 599 String catalog = getClass().getResource("catalog_invalid.xml").toExternalForm(); 600 CatalogFeatures f = CatalogFeatures.builder() 601 .with(Feature.FILES, catalog) 602 .with(Feature.PREFER, "public") 603 .with(Feature.DEFER, "true") 604 .with(Feature.RESOLVE, "ignore") 605 .build(); 606 607 String test = "testInvalidCatalog"; 608 try { 609 CatalogResolver resolver = CatalogManager.catalogResolver(f); 610 String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId(); 611 System.out.println("testIgnoreInvalidCatalog: expected [null]"); 612 System.out.println("testIgnoreInvalidCatalog: expected [null]"); 613 System.out.println("actual [" + actualSystemId + "]"); 614 Assert.assertEquals(actualSystemId, null); 615 } catch (Exception e) { 616 Assert.fail(e.getMessage()); 617 } 618 } 619 620 621 /* 622 DataProvider: used to verify CatalogResolver's resolve function. 623 Data columns: 624 catalog, uri or publicId, expectedFile, expectedUri, msg 625 626 This DataProvider is copied from JCK ResolveTests' dataMatch1 627 */ 628 @DataProvider(name = "resolveUri") 629 public Object[][] getDataForUriResolver() { 630 return new Object[][]{ 631 {"uri.xml", "urn:publicid:-:Acme,+Inc.:DTD+Book+Version+1.0", null, "http://local/base/dtd/book.dtd", "Uri in publicId namespace is incorrectly unwrapped"}, 632 }; 633 } 634 635 /* 636 DataProvider: used to verify hierarchical catalogs. Refer to JCK test 637 hierarchyOfCatFiles2. 638 */ 639 @DataProvider(name = "hierarchyOfCatFilesData") 640 public Object[][] getHierarchyOfCatFilesData() { 641 return new Object[][]{ 642 {"http://www.oracle.com/sequence.dtd", "first.dtd"}, 643 {"http://www.oracle.com/sequence_next.dtd", "next.dtd"}, 644 {"http://www.oracle.com/sequence_second.dtd", "second.dtd"} 645 }; 646 } 647 648 /* 649 DataProvider: used to verify CatalogResolver's resolveEntity function. 650 Data columns: 651 catalog, prefer, systemId, publicId, expectedUri, expectedFile, msg 652 */ 653 @DataProvider(name = "resolveEntity") 654 public Object[][] getDataForMatchingBothIds() { 655 String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd"; 656 return new Object[][]{ 657 {"rewriteSystem_id.xml", "system", "http://www.sys00test.com/rewrite.dtd", "PUB-404", expected, expected, "Relative rewriteSystem with xml:base at group level failed"}, 658 }; 659 } 660 661 static String id = "http://openjdk.java.net/xml/catalog/dtd/system.dtd"; 662 /* 663 DataProvider: used to verify how prefer settings affect the result of the 664 Catalog's matching operation. 665 Data columns: 666 prefer, catalog, publicId, systemId, expected result 667 */ 668 @DataProvider(name = "matchWithPrefer") 669 public Object[][] getDataForMatch() { 670 return new Object[][]{ 671 {"public", "pubOnly.xml", id, "", "http://local/base/dtd/public.dtd"}, 672 {"public", "sysOnly.xml", id, "", null}, 673 {"public", "sysAndPub.xml", id, "", "http://local/base/dtd/public.dtd"}, 674 {"system", "pubOnly.xml", id, "", "http://local/base/dtd/public.dtd"}, 675 {"system", "sysOnly.xml", id, "", null}, 676 {"system", "sysAndPub.xml", id, "", "http://local/base/dtd/public.dtd"}, 677 {"public", "pubOnly.xml", "", id, null}, 678 {"public", "sysOnly.xml", "", id, "http://local/base/dtd/system.dtd"}, 679 {"public", "sysAndPub.xml", "", id, "http://local/base/dtd/system.dtd"}, 680 {"system", "pubOnly.xml", "", id, null}, 681 {"system", "sysOnly.xml", "", id, "http://local/base/dtd/system.dtd"}, 682 {"system", "sysAndPub.xml", "", id, "http://local/base/dtd/system.dtd"}, 683 }; 684 } 685 686 /* 687 DataProvider: used to verify how prefer settings affect the result of the 688 CatalogResolver's resolution operation. 689 Data columns: 690 prefer, catalog, publicId, systemId, expected result 691 */ 692 @DataProvider(name = "resolveWithPrefer") 693 public Object[][] getDataForResolve() { 694 return new Object[][]{ 695 {"system", "pubOnly.xml", id, "", "http://local/base/dtd/public.dtd"}, 696 {"system", "pubOnly.xml", "", id, null}, 697 {"system", "pubOnly.xml", id, id, null}, 698 {"public", "pubOnly.xml", id, "", "http://local/base/dtd/public.dtd"}, 699 {"public", "pubOnly.xml", "", id, null}, 700 {"public", "pubOnly.xml", id, id, "http://local/base/dtd/public.dtd"}, 701 {"system", "sysOnly.xml", id, "", null}, 702 {"system", "sysOnly.xml", "", id, "http://local/base/dtd/system.dtd"}, 703 {"system", "sysOnly.xml", id, id, "http://local/base/dtd/system.dtd"}, 704 {"public", "sysOnly.xml", id, "", null}, 705 {"public", "sysOnly.xml", "", id, "http://local/base/dtd/system.dtd"}, 706 {"public", "sysOnly.xml", id, id, "http://local/base/dtd/system.dtd"}, 707 {"system", "sysAndPub.xml", id, "", "http://local/base/dtd/public.dtd"}, 708 {"system", "sysAndPub.xml", "", id, "http://local/base/dtd/system.dtd"}, 709 {"system", "sysAndPub.xml", id, id, "http://local/base/dtd/system.dtd"}, 710 {"public", "sysAndPub.xml", id, "", "http://local/base/dtd/public.dtd"}, 711 {"public", "sysAndPub.xml", "", id, "http://local/base/dtd/system.dtd"}, 712 {"public", "sysAndPub.xml", id, id, "http://local/base/dtd/system.dtd"}, 713 }; 714 } 715 /* 716 DataProvider: catalogs that contain invalid next or delegate catalogs. 717 The defer attribute is set to false. 718 */ 719 @DataProvider(name = "invalidAltCatalogs") 720 public Object[][] getCatalogs() { 721 return new Object[][]{ 722 {"defer_false_2.xml"}, 723 {"defer_del_false.xml"} 724 }; 725 } 726 727 728 /* 729 DataProvider: provides test name, expected string, the catalog, and XML 730 document. 731 */ 732 @DataProvider(name = "catalog") 733 public Object[][] getCatalog() { 734 return new Object[][]{ 735 {"testSystem", "Test system entry", "catalog.xml", "system.xml", getParser()}, 736 {"testRewriteSystem", "Test rewritesystem entry", "catalog.xml", "rewritesystem.xml", getParser()}, 737 {"testRewriteSystem1", "Test rewritesystem entry", "catalog.xml", "rewritesystem1.xml", getParser()}, 738 {"testSystemSuffix", "Test systemsuffix entry", "catalog.xml", "systemsuffix.xml", getParser()}, 739 {"testDelegateSystem", "Test delegatesystem entry", "catalog.xml", "delegatesystem.xml", getParser()}, 740 {"testPublic", "Test public entry", "catalog.xml", "public.xml", getParser()}, 741 {"testDelegatePublic", "Test delegatepublic entry", "catalog.xml", "delegatepublic.xml", getParser()}, 742 }; 743 } 744 745 SAXParser getParser() { 746 SAXParser saxParser = null; 747 try { 748 SAXParserFactory factory = SAXParserFactory.newInstance(); 749 factory.setNamespaceAware(true); 750 saxParser = factory.newSAXParser(); 751 } catch (ParserConfigurationException | SAXException e) { 752 } 753 754 return saxParser; 755 } 756 757 /** 758 * SAX handler 759 */ 760 public class MyHandler extends DefaultHandler2 implements ErrorHandler { 761 762 StringBuilder textContent = new StringBuilder(); 763 SAXParser saxParser; 764 765 MyHandler(SAXParser saxParser) { 766 textContent.setLength(0); 767 this.saxParser = saxParser; 768 } 769 770 String getResult() { 771 return textContent.toString(); 772 } 773 774 @Override 775 public void startElement(String uri, String localName, String qName, Attributes attributes) 776 throws SAXException { 777 textContent.delete(0, textContent.length()); 778 try { 779 System.out.println("Element: " + uri + ":" + localName + " " + qName); 780 } catch (Exception e) { 781 throw new SAXException(e); 782 } 783 784 } 785 786 @Override 787 public void characters(char ch[], int start, int length) throws SAXException { 788 textContent.append(ch, start, length); 789 } 790 } 791 }