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