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