1 /* 2 * Copyright (c) 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 24 package catalog; 25 26 import static jaxp.library.JAXPTestUtilities.getSystemProperty; 27 28 import java.io.ByteArrayInputStream; 29 import java.io.File; 30 import java.io.FileInputStream; 31 import java.io.FileNotFoundException; 32 import java.io.IOException; 33 import java.io.InputStream; 34 import java.io.Reader; 35 import java.io.StringReader; 36 import java.io.StringWriter; 37 import java.io.UnsupportedEncodingException; 38 import javax.xml.XMLConstants; 39 import javax.xml.catalog.CatalogFeatures; 40 import javax.xml.catalog.CatalogResolver; 41 import javax.xml.parsers.DocumentBuilder; 42 import javax.xml.parsers.DocumentBuilderFactory; 43 import javax.xml.parsers.ParserConfigurationException; 44 import javax.xml.parsers.SAXParser; 45 import javax.xml.parsers.SAXParserFactory; 46 import javax.xml.stream.XMLInputFactory; 47 import javax.xml.stream.XMLResolver; 48 import javax.xml.stream.XMLStreamConstants; 49 import javax.xml.stream.XMLStreamException; 50 import javax.xml.stream.XMLStreamReader; 51 import javax.xml.transform.Source; 52 import javax.xml.transform.Transformer; 53 import javax.xml.transform.TransformerException; 54 import javax.xml.transform.TransformerFactory; 55 import javax.xml.transform.URIResolver; 56 import javax.xml.transform.dom.DOMSource; 57 import javax.xml.transform.sax.SAXSource; 58 import javax.xml.transform.stax.StAXSource; 59 import javax.xml.transform.stream.StreamResult; 60 import javax.xml.transform.stream.StreamSource; 61 import javax.xml.validation.Schema; 62 import javax.xml.validation.SchemaFactory; 63 import javax.xml.validation.Validator; 64 import org.testng.Assert; 65 import org.w3c.dom.Document; 66 import org.w3c.dom.Node; 67 import org.w3c.dom.ls.LSInput; 68 import org.w3c.dom.ls.LSResourceResolver; 69 import org.xml.sax.Attributes; 70 import org.xml.sax.ErrorHandler; 71 import org.xml.sax.InputSource; 72 import org.xml.sax.SAXException; 73 import org.xml.sax.XMLReader; 74 import org.xml.sax.ext.DefaultHandler2; 75 76 /** 77 * Base class: 78 * Initialized xml/xsd/xsl used for the test; 79 * Handler classes 80 * 81 * @author huizhe.wang@oracle.com 82 */ 83 public class CatalogSupportBase { 84 // the System Property for the USE_CATALOG feature 85 final static String SP_USE_CATALOG = "javax.xml.useCatalog"; 86 87 boolean debug = false; 88 89 String filepath; 90 String slash = ""; 91 92 protected void setUp() { 93 String file1 = getClass().getResource("CatalogSupport.xml").getFile(); 94 if (getSystemProperty("os.name").contains("Windows")) { 95 filepath = file1.substring(1, file1.lastIndexOf("/") + 1); 96 slash = "/"; 97 } else { 98 filepath = file1.substring(0, file1.lastIndexOf("/") + 1); 99 } 100 101 initFiles(); 102 } 103 104 String xml_catalog, xml_bogus_catalog; 105 106 // For tests using system.xml 107 String xml_system, dtd_system, dtd_systemResolved; 108 final String elementInSystem = "catalogtest"; 109 final String expectedWCatalog = "Test system entry"; 110 final String expectedWResolver = "Test resolved by an EntityHandler, rather than a Catalog entry"; 111 112 // For tests using XInclude.xml 113 String xml_xInclude, xml_xIncludeSimple; 114 final String elementInXISimple = "blue"; 115 final String contentInXIutf8 = "trjsagdkasgdhasdgashgdhsadgashdg"; 116 final String contentInUIutf8Catalog = "usingCatalog"; 117 118 // For the xsd import and include 119 String xsd_xmlSchema, dtd_xmlSchema, dtd_datatypes; 120 String xsd_xmlSchema_import, xsd_xml; 121 String xml_val_test, xml_val_test_id, xsd_val_test; 122 String xsd_include_company, xsd_include_person, xsd_include_product; 123 String xsl_include, xsl_includeDTD, xsl_import_html, xsl_include_header, xsl_include_footer; 124 125 // For the xsl import and include 126 String xml_xsl, xml_xslDTD; 127 128 // For document function 129 String xml_doc, xsl_doc, xml_doc2; 130 131 void initFiles() { 132 xml_system = filepath + "system.xml"; 133 dtd_system = filepath + "system.dtd"; 134 dtd_systemResolved = "<!ENTITY system \"resolved by an EntityHandler, rather than a Catalog\">"; 135 136 xml_catalog = filepath + "CatalogSupport.xml"; 137 xml_bogus_catalog = filepath + "CatalogSupport_bogus.xml"; 138 139 xml_xInclude = "<?xml version=\"1.0\"?>\n" + 140 "<xinclude:include xmlns:xinclude=\"http://www.w3.org/2001/XInclude\"\n" + 141 " href=\"XI_simple.xml\"/>\n"; 142 xml_xIncludeSimple = filepath + "XI_simple.xml"; 143 144 xsd_xmlSchema = "<?xml version=\"1.1\" encoding=\"UTF-8\"?>" 145 + "<!DOCTYPE xs:schema PUBLIC \"-//W3C//DTD XMLSCHEMA 200102//EN\" \"pathto/XMLSchema.dtd\" >" 146 + "<xs:schema targetNamespace=\"http://www.w3.org/2001/XMLSchema\" blockDefault=\"#all\" " 147 + " elementFormDefault=\"qualified\" version=\"1.0\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" " 148 + " xml:lang=\"EN\" xmlns:hfp=\"http://www.w3.org/2001/XMLSchema-hasFacetAndProperty\">" 149 + " <xs:annotation>" 150 + " <xs:documentation>" 151 + " Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp " 152 + " Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp " 153 + " </xs:documentation>" 154 + " </xs:annotation>" 155 + "</xs:schema>"; 156 dtd_xmlSchema = filepath + "XMLSchema.dtd"; 157 dtd_datatypes = filepath + "datatypes.dtd"; 158 159 xsd_xmlSchema_import = "<?xml version=\"1.1\" encoding=\"UTF-8\"?>" 160 + "<xs:schema targetNamespace=\"http://www.w3.org/2001/XMLSchema\" " 161 + "blockDefault=\"#all\" elementFormDefault=\"qualified\" version=\"1.0\" " 162 + "xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xml:lang=\"EN\" " 163 + "xmlns:hfp=\"http://www.w3.org/2001/XMLSchema-hasFacetAndProperty\">" 164 + " <xs:annotation>" 165 + " <xs:documentation>" 166 + " Part 1 version: Id: structures.xsd,v 1.2 2004/01/15 11:34:25 ht Exp " 167 + " Part 2 version: Id: datatypes.xsd,v 1.3 2004/01/23 18:11:13 ht Exp " 168 + " </xs:documentation>" 169 + " </xs:annotation>" 170 + "" 171 + " <xs:import namespace=\"http://www.w3.org/XML/1998/namespace\" " 172 + "schemaLocation=\"http://www.w3.org/2001/pathto/xml.xsd\">" 173 + " <xs:annotation>" 174 + " <xs:documentation>" 175 + " Get access to the xml: attribute groups for xml:lang" 176 + " as declared on 'schema' and 'documentation' below" 177 + " </xs:documentation>" 178 + " </xs:annotation>" 179 + " </xs:import>" 180 + " <xs:element name=\"schema\" id=\"schema\">" 181 + " <xs:complexType>" 182 + " <xs:simpleContent>" 183 + " <xs:extension base=\"xs:integer\">" 184 + " <xs:attribute ref=\"xml:lang\"/>" 185 + " </xs:extension>" 186 + " </xs:simpleContent>" 187 + " </xs:complexType>" 188 + " </xs:element>" 189 + "</xs:schema>"; 190 191 xsd_xml = filepath + "xml.xsd"; 192 193 xsd_include_company = "<?xml version=\"1.1\"?>" 194 + "<xsd:schema xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"" 195 + " targetNamespace=\"http://www.company.org\"" 196 + " xmlns=\"http://www.company.org\"" 197 + " elementFormDefault=\"qualified\">" 198 + " <xsd:include schemaLocation=\"pathto/XSDInclude_person.xsd\"/>" 199 + " <xsd:include schemaLocation=\"pathto/XSDInclude_product.xsd\"/>" 200 + " <xsd:element name=\"Company\">" 201 + " <xsd:complexType>" 202 + " <xsd:sequence>" 203 + " <xsd:element name=\"Person\" type=\"PersonType\"" 204 + " maxOccurs=\"unbounded\"/>" 205 + " <xsd:element name=\"Product\" type=\"ProductType\"" 206 + " maxOccurs=\"unbounded\"/>" 207 + " </xsd:sequence>" 208 + " </xsd:complexType>" 209 + " </xsd:element>" 210 + "</xsd:schema>"; 211 xsd_include_person = filepath + "XSDInclude_person.xsd"; 212 xsd_include_product = filepath + "XSDInclude_product.xsd"; 213 214 xsl_include = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 215 + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" 216 + " <xsl:import href=\"pathto/XSLImport_html.xsl\"/>" 217 + " <xsl:include href=\"pathto/XSLInclude_header.xsl\"/>" 218 + " " 219 + "" 220 + " <xsl:template match=\"content/title\">" 221 + " <h1><xsl:apply-templates/></h1>" 222 + " </xsl:template>" 223 + " " 224 + " <xsl:include href=\"pathto/XSLInclude_footer.xsl\"/>" 225 + "" 226 + "</xsl:stylesheet>"; 227 xsl_includeDTD = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 228 + "<!DOCTYPE HTMLlat1 SYSTEM \"http://openjdk.java.net/xml/catalog/dtd/XSLDTD.dtd\">" 229 + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">" 230 + " <xsl:import href=\"pathto/XSLImport_html.xsl\"/>" 231 + " <xsl:include href=\"pathto/XSLInclude_header.xsl\"/>" 232 + " " 233 + "" 234 + " <xsl:template match=\"content/title\">" 235 + " <h1><xsl:apply-templates/></h1>" 236 + " </xsl:template>" 237 + " " 238 + " <xsl:include href=\"pathto/XSLInclude_footer.xsl\"/>" 239 + "" 240 + "</xsl:stylesheet>"; 241 242 xsl_import_html = filepath + "XSLImport_html.xsl"; 243 xsl_include_header = filepath + "XSLInclude_header.xsl"; 244 xsl_include_footer = filepath + "XSLInclude_footer.xsl"; 245 246 xml_val_test = filepath + "/val_test.xml"; 247 xml_val_test_id = "file://" + slash + xml_val_test; 248 xsd_val_test = filepath + "/val_test.xsd"; 249 250 xml_xsl = "<?xml version=\"1.0\"?>\n" + 251 "<content>\n" + 252 " <header>This is the header</header>\n" + 253 " Some content\n" + 254 " <footer>footer</footer>\n" + 255 "</content>"; 256 257 xml_xslDTD = "<?xml version=\"1.0\"?>\n" + 258 "<!DOCTYPE content SYSTEM \"http://openjdk.java.net/xml/catalog/dtd/include.dtd\">" + 259 "<content>\n" + 260 " <header>This is the header</header>\n" + 261 " Some content\n" + 262 " <footer>footer</footer>\n" + 263 "</content>"; 264 265 xml_doc = filepath + "/DocFunc.xml"; 266 xsl_doc = filepath + "/DocFunc.xsl"; 267 xml_doc2 = filepath + "/DocFunc2.xml"; 268 } 269 270 271 /* 272 Verifies the Catalog support on SAXParser. 273 */ 274 public void testSAX(boolean setUseCatalog, boolean useCatalog, String catalog, 275 String xml, MyHandler handler, String expected) throws Exception { 276 SAXParser parser = getSAXParser(setUseCatalog, useCatalog, catalog); 277 278 parser.parse(xml, handler); 279 assertEquals(expected, handler.getResult().trim(), ""); 280 } 281 282 /* 283 Verifies the Catalog support on XMLReader. 284 */ 285 public void testXMLReader(boolean setUseCatalog, boolean useCatalog, String catalog, 286 String xml, MyHandler handler, String expected) throws Exception { 287 XMLReader reader = getXMLReader(setUseCatalog, useCatalog, catalog); 288 289 reader.setContentHandler(handler); 290 reader.parse(xml); 291 assertEquals(expected, handler.getResult().trim(), ""); 292 } 293 294 /* 295 Verifies the Catalog support on XInclude. 296 */ 297 public void testXInclude(boolean setUseCatalog, boolean useCatalog, String catalog, 298 String xml, MyHandler handler, String expected) throws Exception { 299 SAXParser parser = getSAXParser(setUseCatalog, useCatalog, catalog); 300 301 parser.parse(new InputSource(new StringReader(xml)), handler); 302 debugPrint("handler.result:" + handler.getResult()); 303 assertEquals(expected, handler.getResult(), "Catalog support for XInclude"); 304 } 305 306 /* 307 Verifies the Catalog support on DOM parser. 308 */ 309 public void testDOM(boolean setUseCatalog, boolean useCatalog, String catalog, 310 String xml, MyHandler handler, String expected) throws Exception { 311 DocumentBuilder docBuilder = getDomBuilder(setUseCatalog, useCatalog, catalog); 312 docBuilder.setEntityResolver(handler); 313 Document doc = docBuilder.parse(xml); 314 315 Node node = doc.getElementsByTagName(elementInSystem).item(0); 316 String result = node.getFirstChild().getTextContent(); 317 318 assertEquals(expected, result.trim(), "Catalog support for DOM"); 319 } 320 321 /* 322 Verifies the Catalog support on resolving DTD, xsd import and include in 323 Schema files. 324 */ 325 public void testValidation(boolean setUseCatalog, boolean useCatalog, String catalog, 326 String xsd, LSResourceResolver resolver) 327 throws Exception { 328 329 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 330 331 // use resolver or catalog if resolver = null 332 if (resolver != null) { 333 factory.setResourceResolver(resolver); 334 } 335 if (setUseCatalog) { 336 factory.setFeature(XMLConstants.USE_CATALOG, useCatalog); 337 } 338 factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 339 340 Schema schema = factory.newSchema(new StreamSource(new StringReader(xsd))); 341 success("XMLSchema.dtd and datatypes.dtd are resolved."); 342 } 343 344 /** 345 * Verifies Catalog Support for the Validator. 346 * @param setUseCatalog1 a flag to indicate whether USE_CATALOG shall be set 347 * on the factory. 348 * @param setUseCatalog2 a flag to indicate whether USE_CATALOG shall be set 349 * on the Validator. 350 * @param source the XML source 351 * @param resolver1 a resolver to be set on the factory if specified 352 * @param resolver2 a resolver to be set on the Validator if specified 353 * @param catalog1 a catalog to be set on the factory if specified 354 * @param catalog2 a catalog to be set on the Validator if specified 355 */ 356 public void testValidator(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, 357 Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, 358 String catalog1, String catalog2) 359 throws Exception { 360 361 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 362 if (setUseCatalog1) { 363 schemaFactory.setFeature(XMLConstants.USE_CATALOG, useCatalog); 364 } 365 if (catalog1 != null) { 366 schemaFactory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog1); 367 } 368 if (resolver1 != null) { 369 schemaFactory.setResourceResolver(resolver1); 370 } 371 372 Schema schema = schemaFactory.newSchema(); 373 Validator validator = schema.newValidator(); 374 if (setUseCatalog2) { 375 validator.setFeature(XMLConstants.USE_CATALOG, useCatalog); 376 } 377 if (catalog2 != null) { 378 validator.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog2); 379 } 380 if (resolver2 != null) { 381 validator.setResourceResolver(resolver2); 382 } 383 validator.validate(source); 384 } 385 386 /* 387 Verifies the Catalog support on resolving DTD, xsl import and include in 388 XSL files. 389 */ 390 public void testXSLImport(boolean setUseCatalog, boolean useCatalog, String catalog, 391 SAXSource xsl, StreamSource xml, 392 URIResolver resolver, String expected) throws Exception { 393 394 TransformerFactory factory = getTransformerFactory(setUseCatalog, useCatalog, catalog, resolver); 395 Transformer transformer = factory.newTransformer(xsl); 396 397 StringWriter out = new StringWriter(); 398 transformer.transform(xml, new StreamResult(out)); 399 debugPrint("out:\n" + out.toString()); 400 Assert.assertTrue(out.toString().contains(expected), "testXSLImport"); 401 } 402 403 /* 404 Verifies the Catalog support on resolving DTD, xsl import and include in 405 XSL files. 406 */ 407 public void testXSLImportWTemplates(boolean setUseCatalog, boolean useCatalog, 408 String catalog, SAXSource xsl, StreamSource xml, 409 URIResolver resolver, String expected) throws Exception { 410 411 TransformerFactory factory = getTransformerFactory(setUseCatalog, useCatalog, catalog, resolver); 412 Transformer transformer = factory.newTemplates(xsl).newTransformer(); 413 StringWriter out = new StringWriter(); 414 transformer.transform(xml, new StreamResult(out)); 415 Assert.assertTrue(out.toString().contains(expected), "testXSLImportWTemplates"); 416 } 417 418 /** 419 * Returns an instance of SAXParser with a catalog if one is provided. 420 * 421 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 422 * through the factory 423 * @param useCatalog the value of USE_CATALOG 424 * @param catalog a catalog 425 * @return an instance of SAXParser 426 * @throws ParserConfigurationException 427 * @throws SAXException 428 */ 429 SAXParser getSAXParser(boolean setUseCatalog, boolean useCatalog, String catalog) 430 throws ParserConfigurationException, SAXException { 431 SAXParserFactory spf = SAXParserFactory.newInstance(); 432 spf.setNamespaceAware(true); 433 spf.setXIncludeAware(true); 434 if (setUseCatalog) { 435 spf.setFeature(XMLConstants.USE_CATALOG, useCatalog); 436 } 437 438 SAXParser parser = spf.newSAXParser(); 439 parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 440 return parser; 441 } 442 443 /** 444 * Returns an instance of XMLReader with a catalog if one is provided. 445 * 446 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 447 * through the factory 448 * @param useCatalog the value of USE_CATALOG 449 * @param catalog a catalog 450 * @return an instance of XMLReader 451 * @throws ParserConfigurationException 452 * @throws SAXException 453 */ 454 XMLReader getXMLReader(boolean setUseCatalog, boolean useCatalog, String catalog) 455 throws ParserConfigurationException, SAXException { 456 SAXParserFactory spf = SAXParserFactory.newInstance(); 457 spf.setNamespaceAware(true); 458 XMLReader reader = spf.newSAXParser().getXMLReader(); 459 if (setUseCatalog) { 460 reader.setFeature(XMLConstants.USE_CATALOG, useCatalog); 461 } 462 reader.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 463 return reader; 464 } 465 466 /** 467 * Returns an instance of DocumentBuilder that may have set a Catalog. 468 * 469 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 470 * through the factory 471 * @param useCatalog the value of USE_CATALOG 472 * @param catalog a catalog 473 * @return an instance of DocumentBuilder 474 * @throws ParserConfigurationException 475 */ 476 DocumentBuilder getDomBuilder(boolean setUseCatalog, boolean useCatalog, String catalog) 477 throws ParserConfigurationException { 478 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 479 dbf.setNamespaceAware(true); 480 if (setUseCatalog) { 481 dbf.setFeature(XMLConstants.USE_CATALOG, useCatalog); 482 } 483 dbf.setAttribute(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 484 DocumentBuilder docBuilder = dbf.newDocumentBuilder(); 485 return docBuilder; 486 } 487 488 /** 489 * Creates a DOMSource. 490 * 491 * @param uri the URI to the XML source file 492 * @param systemId the systemId of the source 493 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 494 * through the factory 495 * @param useCatalog the value of USE_CATALOG 496 * @param catalog a catalog 497 * @return a DOMSource 498 * @throws Exception 499 */ 500 DOMSource getDOMSource(String uri, String systemId, boolean setUseCatalog, 501 boolean useCatalog, String catalog) { 502 DOMSource ds = null; 503 try { 504 DocumentBuilder builder = getDomBuilder(setUseCatalog, useCatalog, catalog); 505 Document doc = builder.parse(new File(uri)); 506 ds = new DOMSource(doc, systemId); 507 } catch (Exception e) {} 508 509 return ds; 510 } 511 512 /** 513 * Creates a StAXSource. 514 * 515 * @param xmlFile the XML source file 516 * @param xmlFileId the systemId of the source 517 * @return a StAXSource 518 * @throws XMLStreamException 519 * @throws FileNotFoundException 520 */ 521 StAXSource getStaxSource(String xmlFile, String xmlFileId) { 522 StAXSource ss = null; 523 try { 524 ss = new StAXSource( 525 XMLInputFactory.newFactory().createXMLEventReader( 526 xmlFileId, new FileInputStream(xmlFile))); 527 } catch (Exception e) {} 528 529 return ss; 530 } 531 532 /** 533 * Creates an XMLStreamReader. 534 * @param catalog the path to a catalog 535 * @param xml the xml to be parsed 536 * @param resolver a resolver to be set on the reader 537 * @return an instance of the XMLStreamReader 538 * @throws FileNotFoundException 539 * @throws XMLStreamException 540 */ 541 XMLStreamReader getStreamReader(boolean setUseCatalog, boolean useCatalog, 542 String catalog, String xml, XMLResolver resolver) 543 throws FileNotFoundException, XMLStreamException { 544 XMLInputFactory factory = XMLInputFactory.newInstance(); 545 factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 546 factory.setProperty(XMLInputFactory.IS_COALESCING, true); 547 factory.setProperty(XMLInputFactory.RESOLVER, resolver); 548 if (setUseCatalog) { 549 factory.setProperty(XMLConstants.USE_CATALOG, useCatalog); 550 } 551 552 InputStream entityxml = new FileInputStream(xml); 553 XMLStreamReader streamReader = factory.createXMLStreamReader(xml, entityxml); 554 return streamReader; 555 } 556 557 /** 558 * Returns the text of the first element found by the reader. 559 * @param streamReader the XMLStreamReader 560 * @return the text of the first element 561 * @throws XMLStreamException 562 */ 563 String getText(XMLStreamReader streamReader) throws XMLStreamException { 564 while(streamReader.hasNext()){ 565 int eventType = streamReader.next() ; 566 if(eventType == XMLStreamConstants.START_ELEMENT){ 567 eventType = streamReader.next() ; 568 if(eventType == XMLStreamConstants.CHARACTERS){ 569 return streamReader.getText() ; 570 } 571 } 572 } 573 return null; 574 } 575 576 /** 577 * Returns an instance of TransformerFactory with either a custom URIResolver 578 * or Catalog. 579 * 580 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 581 * through the factory 582 * @param useCatalog the value of USE_CATALOG 583 * @param catalog a catalog 584 * @param resolver a custom resolver 585 * @return an instance of TransformerFactory 586 * @throws Exception 587 */ 588 TransformerFactory getTransformerFactory(boolean setUseCatalog, boolean useCatalog, 589 String catalog, URIResolver resolver) 590 throws Exception { 591 592 TransformerFactory factory = TransformerFactory.newInstance(); 593 if (setUseCatalog) { 594 factory.setFeature(XMLConstants.USE_CATALOG, useCatalog); 595 } 596 if (catalog != null) { 597 factory.setAttribute(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 598 } 599 600 // use resolver or catalog if resolver = null 601 if (resolver != null) { 602 factory.setURIResolver(resolver); 603 } 604 605 return factory; 606 } 607 608 void assertNotNull(Object obj, String msg) { 609 if (obj == null) { 610 debugPrint("Test failed: " + msg); 611 } else { 612 debugPrint("Test passed: " + obj + " is not null"); 613 } 614 } 615 616 void assertEquals(String expected, String actual, String msg) { 617 if (!expected.equals(actual)) { 618 debugPrint("Test failed: " + msg); 619 } else { 620 debugPrint("Test passed: "); 621 } 622 debugPrint("Expected: " + expected); 623 debugPrint("Actual: " + actual); 624 } 625 626 void fail(String msg) { 627 System.out.println("Test failed:"); 628 System.out.println(msg); 629 } 630 631 void success(String msg) { 632 System.out.println("Test succeded:"); 633 System.out.println(msg); 634 } 635 636 void debugPrint(String msg) { 637 if (debug) { 638 System.out.println(msg); 639 } 640 } 641 642 /** 643 * Extends MyStaxResolver to override resolveEntity 644 */ 645 class MyStaxEntityResolver implements XMLResolver { 646 647 public MyStaxEntityResolver() { 648 649 } 650 651 public Object resolveEntity(String publicId, String systemId, String baseURI, 652 String namespace) 653 throws javax.xml.stream.XMLStreamException { 654 try { 655 return new ByteArrayInputStream( 656 "<!ENTITY system \"resolved by an EntityHandler, rather than a Catalog\">".getBytes("UTF-8")); 657 } catch (UnsupportedEncodingException ex) { 658 return null; 659 } 660 } 661 662 } 663 664 /** 665 * A custom XMLResolver 666 */ 667 class MyStaxResolver implements XMLResolver { 668 669 public MyStaxResolver() { 670 } 671 672 public Object resolveEntity(String publicId, String systemId, String baseURI, 673 String namespace) throws javax.xml.stream.XMLStreamException { 674 return null; 675 } 676 677 } 678 679 680 /** 681 * Extends MyHandler and overrides resolveEntity with a CatalogResolver 682 */ 683 class MyCatalogHandler extends MyHandler { 684 CatalogResolver cr; 685 686 public MyCatalogHandler(CatalogResolver cr, String elementName) { 687 super(elementName); 688 this.cr = cr; 689 } 690 691 @Override 692 public InputSource resolveEntity(String publicId, String systemId) { 693 return cr.resolveEntity(publicId, systemId); 694 } 695 @Override 696 public InputSource resolveEntity(String name, String publicId, 697 String baseURI, String systemId) { 698 return cr.resolveEntity(publicId, systemId); 699 } 700 } 701 702 /** 703 * Extends MyHandler and overrides resolveEntity 704 */ 705 class MyEntityHandler extends MyHandler { 706 String[] systemIds; 707 InputSource[] returnValues; 708 public MyEntityHandler(String[] systemIds, InputSource[] returnValues, String elementName) { 709 super(elementName); 710 this.systemIds = systemIds; 711 this.returnValues = returnValues; 712 } 713 714 @Override 715 public InputSource resolveEntity(String name, String publicId, 716 String baseURI, String systemId) { 717 for (int i = 0; i < systemIds.length; i++) { 718 if (systemId.endsWith(systemIds[i])) { 719 return returnValues[i]; 720 } 721 } 722 723 return null; 724 } 725 } 726 727 /** 728 * SAX handler 729 */ 730 public class MyHandler extends DefaultHandler2 implements ErrorHandler { 731 732 String elementName, currentElementName, result; 733 StringBuilder textContent = new StringBuilder(); 734 735 /** 736 * 737 * @param elementName the name of the element from which the content 738 * is to be captured 739 */ 740 MyHandler(String elementName) { 741 textContent.setLength(0); 742 this.elementName = elementName; 743 } 744 745 String getResult() { 746 return result.trim(); 747 } 748 749 public void startDocument() throws SAXException { 750 } 751 752 public void endDocument() throws SAXException { 753 } 754 755 public void startElement(String uri, String localName, String qName, Attributes attributes) 756 throws SAXException { 757 currentElementName = localName; 758 textContent.delete(0, textContent.length()); 759 try { 760 debugPrint("Element: " + uri + ":" + localName + " " + qName); 761 } catch (Exception e) { 762 throw new SAXException(e); 763 } 764 765 } 766 767 public void endElement(String uri, String localName, String qName) throws SAXException { 768 debugPrint("Text: " + textContent.toString() + ""); 769 debugPrint("End Element: " + uri + ":" + localName + " " + qName); 770 if (currentElementName.equals(elementName)) { 771 result = textContent.toString(); 772 } 773 } 774 775 public void characters(char ch[], int start, int length) throws SAXException { 776 if (currentElementName.equals(elementName)) { 777 textContent.append(ch, start, length); 778 } 779 } 780 781 public void internalEntityDecl(String name, String value) throws SAXException { 782 super.internalEntityDecl(name, value); 783 debugPrint("internalEntityDecl() is invoked for entity : " + name); 784 } 785 786 public void externalEntityDecl(String name, String publicId, String systemId) 787 throws SAXException { 788 super.externalEntityDecl(name, publicId, systemId); 789 debugPrint("externalEntityDecl() is invoked for entity : " + name); 790 } 791 792 public void startEntity(String name) throws SAXException { 793 super.startEntity(name); 794 // debugPrint("startEntity() is invoked for entity : " + name) ; 795 } 796 797 public void endEntity(String name) throws SAXException { 798 super.endEntity(name); 799 // debugPrint("endEntity() is invoked for entity : " + name) ; 800 } 801 802 public InputSource resolveEntity(String publicId, String systemId) 803 throws SAXException, IOException { 804 debugPrint("resolveEntity(publicId, systemId) is invoked"); 805 return super.resolveEntity(publicId, systemId); 806 } 807 808 /** 809 * public InputSource resolveEntity(String name, String publicId, String 810 * baseURI, String systemId) throws SAXException, IOException { 811 * System.out.println("resolveEntity(name, publicId, baseURI, systemId) 812 * is invoked"); return super.resolveEntity(name, publicId, baseURI, 813 * systemId); } 814 */ 815 public InputSource getExternalSubset(String name, String baseURI) 816 throws SAXException, IOException { 817 debugPrint("getExternalSubset() is invoked"); 818 return super.getExternalSubset(name, baseURI); 819 } 820 } 821 822 /** 823 * The purpose of this class, vs an anonymous class, is to show clearly what 824 * we're testing by passing the parameters to the constructor. 825 */ 826 class SourceResolver implements LSResourceResolver { 827 828 String publicId; 829 String[] systemIds; 830 XmlInput[] returnValues; 831 832 public SourceResolver(String publicId, String[] systemIds, XmlInput[] returnValues) { 833 this.publicId = publicId; 834 this.systemIds = systemIds; 835 this.returnValues = returnValues; 836 } 837 838 @Override 839 public LSInput resolveResource(String type, String namespaceURI, String publicId, 840 String systemId, String baseURI) { 841 for (int i = 0; i < systemIds.length; i++) { 842 if (systemId.endsWith(systemIds[i])) { 843 return returnValues[i]; 844 } 845 } 846 847 return null; 848 } 849 } 850 851 class XmlInput implements LSInput { 852 853 private InputStream inputStream; 854 private String systemId; 855 private String baseUri; 856 857 public XmlInput(InputStream inputStream, String systemId, String baseUri) { 858 this.inputStream = inputStream; 859 this.systemId = systemId; 860 this.baseUri = baseUri; 861 } 862 863 @Override 864 public Reader getCharacterStream() { 865 return null; 866 } 867 868 @Override 869 public void setCharacterStream(Reader characterStream) { 870 } 871 872 @Override 873 public InputStream getByteStream() { 874 return inputStream; 875 } 876 877 @Override 878 public void setByteStream(InputStream byteStream) { 879 this.inputStream = byteStream; 880 } 881 882 @Override 883 public String getStringData() { 884 return null; 885 } 886 887 @Override 888 public void setStringData(String stringData) { 889 } 890 891 @Override 892 public String getSystemId() { 893 return systemId; 894 } 895 896 @Override 897 public void setSystemId(String systemId) { 898 this.systemId = systemId; 899 } 900 901 @Override 902 public String getPublicId() { 903 return null; 904 } 905 906 @Override 907 public void setPublicId(String publicId) { 908 } 909 910 @Override 911 public String getBaseURI() { 912 return baseUri; 913 } 914 915 @Override 916 public void setBaseURI(String baseURI) { 917 this.baseUri = baseURI; 918 } 919 920 @Override 921 public String getEncoding() { 922 return null; 923 } 924 925 @Override 926 public void setEncoding(String encoding) { 927 } 928 929 @Override 930 public boolean getCertifiedText() { 931 return false; 932 } 933 934 @Override 935 public void setCertifiedText(boolean certifiedText) { 936 } 937 } 938 939 class XslResolver implements URIResolver { 940 941 String[] hrefs; 942 Source[] returnValues; 943 944 public XslResolver(String[] href, Source[] returnValues) { 945 this.hrefs = href; 946 this.returnValues = returnValues; 947 } 948 949 @Override 950 public Source resolve(String href, String base) throws TransformerException { 951 for (int i = 0; i < hrefs.length; i++) { 952 if (href.endsWith(hrefs[i])) { 953 return returnValues[i]; 954 } 955 } 956 return null; 957 } 958 } 959 }