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 StAX parser. 323 */ 324 public void testStAX(boolean setUseCatalog, boolean useCatalog, String catalog, 325 String xml, XMLResolver resolver, String expected) throws Exception { 326 327 XMLStreamReader streamReader = getStreamReader( 328 setUseCatalog, useCatalog, catalog, xml, resolver); 329 String text = getText(streamReader, XMLStreamConstants.CHARACTERS); 330 assertEquals(expected, text.trim(), "Catalog support for StAX"); 331 } 332 333 /* 334 Verifies that the Catalog support for StAX parser is disabled when 335 USE_CATALOG == false. 336 */ 337 public void testStAXNegative(boolean setUseCatalog, boolean useCatalog, String catalog, 338 String xml, XMLResolver resolver, String expected) throws Exception { 339 340 XMLStreamReader streamReader = getStreamReader( 341 setUseCatalog, useCatalog, catalog, xml, resolver); 342 String text = getText(streamReader, XMLStreamConstants.ENTITY_REFERENCE); 343 assertEquals(expected, text.trim(), "Catalog support for StAX"); 344 } 345 346 /* 347 Verifies the Catalog support on resolving DTD, xsd import and include in 348 Schema files. 349 */ 350 public void testValidation(boolean setUseCatalog, boolean useCatalog, String catalog, 351 String xsd, LSResourceResolver resolver) 352 throws Exception { 353 354 SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 355 356 // use resolver or catalog if resolver = null 357 if (resolver != null) { 358 factory.setResourceResolver(resolver); 359 } 360 if (setUseCatalog) { 361 factory.setFeature(XMLConstants.USE_CATALOG, useCatalog); 362 } 363 factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 364 365 Schema schema = factory.newSchema(new StreamSource(new StringReader(xsd))); 366 success("XMLSchema.dtd and datatypes.dtd are resolved."); 367 } 368 369 /** 370 * Verifies Catalog Support for the Validator. 371 * @param setUseCatalog1 a flag to indicate whether USE_CATALOG shall be set 372 * on the factory. 373 * @param setUseCatalog2 a flag to indicate whether USE_CATALOG shall be set 374 * on the Validator. 375 * @param source the XML source 376 * @param resolver1 a resolver to be set on the factory if specified 377 * @param resolver2 a resolver to be set on the Validator if specified 378 * @param catalog1 a catalog to be set on the factory if specified 379 * @param catalog2 a catalog to be set on the Validator if specified 380 */ 381 public void testValidator(boolean setUseCatalog1, boolean setUseCatalog2, boolean useCatalog, 382 Source source, LSResourceResolver resolver1, LSResourceResolver resolver2, 383 String catalog1, String catalog2) 384 throws Exception { 385 386 SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 387 if (setUseCatalog1) { 388 schemaFactory.setFeature(XMLConstants.USE_CATALOG, useCatalog); 389 } 390 if (catalog1 != null) { 391 schemaFactory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog1); 392 } 393 if (resolver1 != null) { 394 schemaFactory.setResourceResolver(resolver1); 395 } 396 397 Schema schema = schemaFactory.newSchema(); 398 Validator validator = schema.newValidator(); 399 if (setUseCatalog2) { 400 validator.setFeature(XMLConstants.USE_CATALOG, useCatalog); 401 } 402 if (catalog2 != null) { 403 validator.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog2); 404 } 405 if (resolver2 != null) { 406 validator.setResourceResolver(resolver2); 407 } 408 validator.validate(source); 409 } 410 411 /* 412 Verifies the Catalog support on resolving DTD, xsl import and include in 413 XSL files. 414 */ 415 public void testXSLImport(boolean setUseCatalog, boolean useCatalog, String catalog, 416 SAXSource xsl, StreamSource xml, 417 URIResolver resolver, String expected) throws Exception { 418 419 TransformerFactory factory = getTransformerFactory(setUseCatalog, useCatalog, catalog, resolver); 420 Transformer transformer = factory.newTransformer(xsl); 421 422 StringWriter out = new StringWriter(); 423 transformer.transform(xml, new StreamResult(out)); 424 debugPrint("out:\n" + out.toString()); 425 Assert.assertTrue(out.toString().contains(expected), "testXSLImport"); 426 } 427 428 /* 429 Verifies the Catalog support on resolving DTD, xsl import and include in 430 XSL files. 431 */ 432 public void testXSLImportWTemplates(boolean setUseCatalog, boolean useCatalog, 433 String catalog, SAXSource xsl, StreamSource xml, 434 URIResolver resolver, String expected) throws Exception { 435 436 TransformerFactory factory = getTransformerFactory(setUseCatalog, useCatalog, catalog, resolver); 437 Transformer transformer = factory.newTemplates(xsl).newTransformer(); 438 StringWriter out = new StringWriter(); 439 transformer.transform(xml, new StreamResult(out)); 440 Assert.assertTrue(out.toString().contains(expected), "testXSLImportWTemplates"); 441 } 442 443 /** 444 * Returns an instance of SAXParser 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 SAXParser 451 * @throws ParserConfigurationException 452 * @throws SAXException 453 */ 454 SAXParser getSAXParser(boolean setUseCatalog, boolean useCatalog, String catalog) 455 throws ParserConfigurationException, SAXException { 456 SAXParserFactory spf = SAXParserFactory.newInstance(); 457 spf.setNamespaceAware(true); 458 spf.setXIncludeAware(true); 459 if (setUseCatalog) { 460 spf.setFeature(XMLConstants.USE_CATALOG, useCatalog); 461 } 462 463 SAXParser parser = spf.newSAXParser(); 464 parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 465 return parser; 466 } 467 468 /** 469 * Returns an instance of XMLReader with a catalog if one is provided. 470 * 471 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 472 * through the factory 473 * @param useCatalog the value of USE_CATALOG 474 * @param catalog a catalog 475 * @return an instance of XMLReader 476 * @throws ParserConfigurationException 477 * @throws SAXException 478 */ 479 XMLReader getXMLReader(boolean setUseCatalog, boolean useCatalog, String catalog) 480 throws ParserConfigurationException, SAXException { 481 SAXParserFactory spf = SAXParserFactory.newInstance(); 482 spf.setNamespaceAware(true); 483 XMLReader reader = spf.newSAXParser().getXMLReader(); 484 if (setUseCatalog) { 485 reader.setFeature(XMLConstants.USE_CATALOG, useCatalog); 486 } 487 reader.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 488 return reader; 489 } 490 491 /** 492 * Returns an instance of DocumentBuilder that may have set a Catalog. 493 * 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 an instance of DocumentBuilder 499 * @throws ParserConfigurationException 500 */ 501 DocumentBuilder getDomBuilder(boolean setUseCatalog, boolean useCatalog, String catalog) 502 throws ParserConfigurationException { 503 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 504 dbf.setNamespaceAware(true); 505 if (setUseCatalog) { 506 dbf.setFeature(XMLConstants.USE_CATALOG, useCatalog); 507 } 508 dbf.setAttribute(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 509 DocumentBuilder docBuilder = dbf.newDocumentBuilder(); 510 return docBuilder; 511 } 512 513 /** 514 * Creates a DOMSource. 515 * 516 * @param uri the URI to the XML source file 517 * @param systemId the systemId of the source 518 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 519 * through the factory 520 * @param useCatalog the value of USE_CATALOG 521 * @param catalog a catalog 522 * @return a DOMSource 523 * @throws Exception 524 */ 525 DOMSource getDOMSource(String uri, String systemId, boolean setUseCatalog, 526 boolean useCatalog, String catalog) { 527 DOMSource ds = null; 528 try { 529 DocumentBuilder builder = getDomBuilder(setUseCatalog, useCatalog, catalog); 530 Document doc = builder.parse(new File(uri)); 531 ds = new DOMSource(doc, systemId); 532 } catch (Exception e) {} 533 534 return ds; 535 } 536 537 /** 538 * Creates a StAXSource. 539 * 540 * @param xmlFile the XML source file 541 * @param xmlFileId the systemId of the source 542 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 543 * through the factory 544 * @param useCatalog the value of USE_CATALOG 545 * @param catalog a catalog 546 * @return a StAXSource 547 * @throws XMLStreamException 548 * @throws FileNotFoundException 549 */ 550 StAXSource getStaxSource(String xmlFile, String xmlFileId, boolean setUseCatalog, 551 boolean useCatalog, String catalog) { 552 StAXSource ss = null; 553 try { 554 XMLInputFactory xif = XMLInputFactory.newFactory(); 555 if (setUseCatalog) { 556 xif.setProperty(XMLConstants.USE_CATALOG, useCatalog); 557 } 558 xif.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 559 ss = new StAXSource(xif.createXMLEventReader( 560 xmlFileId, new FileInputStream(xmlFile))); 561 } catch (Exception e) {} 562 563 return ss; 564 } 565 566 /** 567 * Creates an XMLStreamReader. 568 * 569 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 570 * through the factory 571 * @param useCatalog the value of USE_CATALOG 572 * @param catalog the path to a catalog 573 * @param xml the xml to be parsed 574 * @param resolver a resolver to be set on the reader 575 * @return an instance of the XMLStreamReader 576 * @throws FileNotFoundException 577 * @throws XMLStreamException 578 */ 579 XMLStreamReader getStreamReader(boolean setUseCatalog, boolean useCatalog, 580 String catalog, String xml, XMLResolver resolver) 581 throws FileNotFoundException, XMLStreamException { 582 XMLInputFactory factory = XMLInputFactory.newInstance(); 583 if (catalog != null) { 584 factory.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 585 } 586 587 factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true); 588 factory.setProperty(XMLInputFactory.IS_COALESCING, true); 589 590 if (resolver != null) { 591 factory.setProperty(XMLInputFactory.RESOLVER, resolver); 592 } 593 594 if (setUseCatalog) { 595 factory.setProperty(XMLConstants.USE_CATALOG, useCatalog); 596 } 597 598 InputStream entityxml = new FileInputStream(xml); 599 XMLStreamReader streamReader = factory.createXMLStreamReader(xml, entityxml); 600 return streamReader; 601 } 602 603 /** 604 * Returns the text of the first element found by the reader. 605 * @param streamReader the XMLStreamReader 606 * @return the text of the first element 607 * @throws XMLStreamException 608 */ 609 String getText(XMLStreamReader streamReader, int type) throws XMLStreamException { 610 StringBuilder text = new StringBuilder(); 611 StringBuilder entityRef = new StringBuilder(); 612 613 while(streamReader.hasNext()){ 614 int eventType = streamReader.next(); 615 switch (eventType) { 616 case XMLStreamConstants.START_ELEMENT: 617 break; 618 case XMLStreamConstants.CHARACTERS: 619 text.append(streamReader.getText()); 620 break; 621 case XMLStreamConstants.ENTITY_REFERENCE: 622 entityRef.append(streamReader.getText()); 623 break; 624 } 625 } 626 if (type == XMLStreamConstants.CHARACTERS) { 627 return text.toString(); 628 } else { 629 return entityRef.toString(); 630 } 631 } 632 633 /** 634 * Returns an instance of TransformerFactory with either a custom URIResolver 635 * or Catalog. 636 * 637 * @param setUseCatalog a flag indicates whether USE_CATALOG shall be set 638 * through the factory 639 * @param useCatalog the value of USE_CATALOG 640 * @param catalog a catalog 641 * @param resolver a custom resolver 642 * @return an instance of TransformerFactory 643 * @throws Exception 644 */ 645 TransformerFactory getTransformerFactory(boolean setUseCatalog, boolean useCatalog, 646 String catalog, URIResolver resolver) 647 throws Exception { 648 649 TransformerFactory factory = TransformerFactory.newInstance(); 650 if (setUseCatalog) { 651 factory.setFeature(XMLConstants.USE_CATALOG, useCatalog); 652 } 653 if (catalog != null) { 654 factory.setAttribute(CatalogFeatures.Feature.FILES.getPropertyName(), catalog); 655 } 656 657 // use resolver or catalog if resolver = null 658 if (resolver != null) { 659 factory.setURIResolver(resolver); 660 } 661 662 return factory; 663 } 664 665 void assertNotNull(Object obj, String msg) { 666 if (obj == null) { 667 debugPrint("Test failed: " + msg); 668 } else { 669 debugPrint("Test passed: " + obj + " is not null"); 670 } 671 } 672 673 void assertEquals(String expected, String actual, String msg) { 674 if (!expected.equals(actual)) { 675 debugPrint("Test failed: " + msg); 676 } else { 677 debugPrint("Test passed: "); 678 } 679 debugPrint("Expected: " + expected); 680 debugPrint("Actual: " + actual); 681 } 682 683 void fail(String msg) { 684 System.out.println("Test failed:"); 685 System.out.println(msg); 686 } 687 688 void success(String msg) { 689 System.out.println("Test succeded:"); 690 System.out.println(msg); 691 } 692 693 void debugPrint(String msg) { 694 if (debug) { 695 System.out.println(msg); 696 } 697 } 698 699 /** 700 * Extends MyStaxResolver to override resolveEntity 701 */ 702 class MyStaxEntityResolver implements XMLResolver { 703 704 public MyStaxEntityResolver() { 705 706 } 707 708 public Object resolveEntity(String publicId, String systemId, String baseURI, 709 String namespace) 710 throws javax.xml.stream.XMLStreamException { 711 try { 712 return new ByteArrayInputStream( 713 "<!ENTITY system \"resolved by an EntityHandler, rather than a Catalog\">".getBytes("UTF-8")); 714 } catch (UnsupportedEncodingException ex) { 715 return null; 716 } 717 } 718 719 } 720 721 /** 722 * A custom XMLResolver 723 */ 724 class MyStaxResolver implements XMLResolver { 725 726 public MyStaxResolver() { 727 } 728 729 public Object resolveEntity(String publicId, String systemId, String baseURI, 730 String namespace) throws javax.xml.stream.XMLStreamException { 731 return null; 732 } 733 734 } 735 736 737 /** 738 * Extends MyHandler and overrides resolveEntity with a CatalogResolver 739 */ 740 class MyCatalogHandler extends MyHandler { 741 CatalogResolver cr; 742 743 public MyCatalogHandler(CatalogResolver cr, String elementName) { 744 super(elementName); 745 this.cr = cr; 746 } 747 748 @Override 749 public InputSource resolveEntity(String publicId, String systemId) { 750 return cr.resolveEntity(publicId, systemId); 751 } 752 @Override 753 public InputSource resolveEntity(String name, String publicId, 754 String baseURI, String systemId) { 755 return cr.resolveEntity(publicId, systemId); 756 } 757 } 758 759 /** 760 * Extends MyHandler and overrides resolveEntity 761 */ 762 class MyEntityHandler extends MyHandler { 763 String[] systemIds; 764 InputSource[] returnValues; 765 public MyEntityHandler(String[] systemIds, InputSource[] returnValues, String elementName) { 766 super(elementName); 767 this.systemIds = systemIds; 768 this.returnValues = returnValues; 769 } 770 771 @Override 772 public InputSource resolveEntity(String name, String publicId, 773 String baseURI, String systemId) { 774 for (int i = 0; i < systemIds.length; i++) { 775 if (systemId.endsWith(systemIds[i])) { 776 return returnValues[i]; 777 } 778 } 779 780 return null; 781 } 782 } 783 784 /** 785 * SAX handler 786 */ 787 public class MyHandler extends DefaultHandler2 implements ErrorHandler { 788 789 String elementName, currentElementName, result; 790 StringBuilder textContent = new StringBuilder(); 791 792 /** 793 * 794 * @param elementName the name of the element from which the content 795 * is to be captured 796 */ 797 MyHandler(String elementName) { 798 textContent.setLength(0); 799 this.elementName = elementName; 800 } 801 802 String getResult() { 803 return result.trim(); 804 } 805 806 public void startDocument() throws SAXException { 807 } 808 809 public void endDocument() throws SAXException { 810 } 811 812 public void startElement(String uri, String localName, String qName, Attributes attributes) 813 throws SAXException { 814 currentElementName = localName; 815 textContent.delete(0, textContent.length()); 816 try { 817 debugPrint("Element: " + uri + ":" + localName + " " + qName); 818 } catch (Exception e) { 819 throw new SAXException(e); 820 } 821 822 } 823 824 public void endElement(String uri, String localName, String qName) throws SAXException { 825 debugPrint("Text: " + textContent.toString() + ""); 826 debugPrint("End Element: " + uri + ":" + localName + " " + qName); 827 if (currentElementName.equals(elementName)) { 828 result = textContent.toString(); 829 } 830 } 831 832 public void characters(char ch[], int start, int length) throws SAXException { 833 if (currentElementName.equals(elementName)) { 834 textContent.append(ch, start, length); 835 } 836 } 837 838 public void internalEntityDecl(String name, String value) throws SAXException { 839 super.internalEntityDecl(name, value); 840 debugPrint("internalEntityDecl() is invoked for entity : " + name); 841 } 842 843 public void externalEntityDecl(String name, String publicId, String systemId) 844 throws SAXException { 845 super.externalEntityDecl(name, publicId, systemId); 846 debugPrint("externalEntityDecl() is invoked for entity : " + name); 847 } 848 849 public void startEntity(String name) throws SAXException { 850 super.startEntity(name); 851 // debugPrint("startEntity() is invoked for entity : " + name) ; 852 } 853 854 public void endEntity(String name) throws SAXException { 855 super.endEntity(name); 856 // debugPrint("endEntity() is invoked for entity : " + name) ; 857 } 858 859 public InputSource resolveEntity(String publicId, String systemId) 860 throws SAXException, IOException { 861 debugPrint("resolveEntity(publicId, systemId) is invoked"); 862 return super.resolveEntity(publicId, systemId); 863 } 864 865 /** 866 * public InputSource resolveEntity(String name, String publicId, String 867 * baseURI, String systemId) throws SAXException, IOException { 868 * System.out.println("resolveEntity(name, publicId, baseURI, systemId) 869 * is invoked"); return super.resolveEntity(name, publicId, baseURI, 870 * systemId); } 871 */ 872 public InputSource getExternalSubset(String name, String baseURI) 873 throws SAXException, IOException { 874 debugPrint("getExternalSubset() is invoked"); 875 return super.getExternalSubset(name, baseURI); 876 } 877 } 878 879 /** 880 * The purpose of this class, vs an anonymous class, is to show clearly what 881 * we're testing by passing the parameters to the constructor. 882 */ 883 class SourceResolver implements LSResourceResolver { 884 885 String publicId; 886 String[] systemIds; 887 XmlInput[] returnValues; 888 889 public SourceResolver(String publicId, String[] systemIds, XmlInput[] returnValues) { 890 this.publicId = publicId; 891 this.systemIds = systemIds; 892 this.returnValues = returnValues; 893 } 894 895 @Override 896 public LSInput resolveResource(String type, String namespaceURI, String publicId, 897 String systemId, String baseURI) { 898 for (int i = 0; i < systemIds.length; i++) { 899 if (systemId.endsWith(systemIds[i])) { 900 return returnValues[i]; 901 } 902 } 903 904 return null; 905 } 906 } 907 908 class XmlInput implements LSInput { 909 910 private InputStream inputStream; 911 private String systemId; 912 private String baseUri; 913 914 public XmlInput(InputStream inputStream, String systemId, String baseUri) { 915 this.inputStream = inputStream; 916 this.systemId = systemId; 917 this.baseUri = baseUri; 918 } 919 920 @Override 921 public Reader getCharacterStream() { 922 return null; 923 } 924 925 @Override 926 public void setCharacterStream(Reader characterStream) { 927 } 928 929 @Override 930 public InputStream getByteStream() { 931 return inputStream; 932 } 933 934 @Override 935 public void setByteStream(InputStream byteStream) { 936 this.inputStream = byteStream; 937 } 938 939 @Override 940 public String getStringData() { 941 return null; 942 } 943 944 @Override 945 public void setStringData(String stringData) { 946 } 947 948 @Override 949 public String getSystemId() { 950 return systemId; 951 } 952 953 @Override 954 public void setSystemId(String systemId) { 955 this.systemId = systemId; 956 } 957 958 @Override 959 public String getPublicId() { 960 return null; 961 } 962 963 @Override 964 public void setPublicId(String publicId) { 965 } 966 967 @Override 968 public String getBaseURI() { 969 return baseUri; 970 } 971 972 @Override 973 public void setBaseURI(String baseURI) { 974 this.baseUri = baseURI; 975 } 976 977 @Override 978 public String getEncoding() { 979 return null; 980 } 981 982 @Override 983 public void setEncoding(String encoding) { 984 } 985 986 @Override 987 public boolean getCertifiedText() { 988 return false; 989 } 990 991 @Override 992 public void setCertifiedText(boolean certifiedText) { 993 } 994 } 995 996 class XslResolver implements URIResolver { 997 998 String[] hrefs; 999 Source[] returnValues; 1000 1001 public XslResolver(String[] href, Source[] returnValues) { 1002 this.hrefs = href; 1003 this.returnValues = returnValues; 1004 } 1005 1006 @Override 1007 public Source resolve(String href, String base) throws TransformerException { 1008 for (int i = 0; i < hrefs.length; i++) { 1009 if (href.endsWith(hrefs[i])) { 1010 return returnValues[i]; 1011 } 1012 } 1013 return null; 1014 } 1015 } 1016 }