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