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