1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 package org.apache.qetest.trax;
  21 
  22 import java.io.IOException;
  23 import javax.xml.parsers.DocumentBuilder;
  24 import javax.xml.parsers.DocumentBuilderFactory;
  25 import javax.xml.parsers.ParserConfigurationException;
  26 import javax.xml.parsers.SAXParserFactory;
  27 import javax.xml.transform.Result;
  28 import javax.xml.transform.Templates;
  29 import javax.xml.transform.Transformer;
  30 import javax.xml.transform.TransformerConfigurationException;
  31 import javax.xml.transform.TransformerException;
  32 import javax.xml.transform.TransformerFactory;
  33 import javax.xml.transform.dom.DOMSource;
  34 import javax.xml.transform.sax.SAXSource;
  35 import javax.xml.transform.sax.SAXTransformerFactory;
  36 import javax.xml.transform.sax.TransformerHandler;
  37 import javax.xml.transform.stream.StreamResult;
  38 import javax.xml.transform.stream.StreamSource;
  39 import jaxp.library.JAXPFileBaseTest;
  40 import static jaxp.library.JAXPTestUtilities.compareWithGold;
  41 import static jaxp.library.JAXPTestUtilities.filenameToURL;
  42 import static jaxp.library.JAXPTestUtilities.getNextFile;
  43 import static org.apache.qetest.CheckingHandler.Expectation.ITEM_CHECKFAIL;
  44 import static org.apache.qetest.trax.CheckingErrorListener.THROW_NEVER;
  45 import static org.apache.qetest.trax.CheckingErrorListener.TYPE_FATALERROR;
  46 import static org.apache.qetest.trax.CheckingErrorListener.TYPE_WARNING;
  47 import static org.apache.qetest.trax.TraxConst.GOLDEN_DIR;
  48 import static org.apache.qetest.trax.TraxConst.XML_DIR;
  49 import org.apache.qetest.xsl.CheckingSAXErrorHandler;
  50 import org.testng.annotations.DataProvider;
  51 import org.testng.annotations.Test;
  52 import org.w3c.dom.Node;
  53 import org.xml.sax.InputSource;
  54 import org.xml.sax.SAXException;
  55 import org.xml.sax.XMLReader;
  56 
  57 /**
  58  * Verify that ErrorListeners are called properly from Transformers. Also
  59  * verifies basic Transformer behavior after a stylesheet with errors has been
  60  * built. Note: parts of this test may rely on specific Xalan functionality, in
  61  * that with the specific errors I've chosen, Xalan can actually continue to
  62  * process the stylesheet, even though it had an error. XSLTC mode may either
  63  * throw slighly different kinds of errors, or may not be able to continue after
  64  * the error (we should investigate changing this test to just verify common
  65  * things, and then check the rest into the xalanj2 directory).
  66  */
  67 public class ErrorListenerTest extends JAXPFileBaseTest {
  68     /**
  69      * Expect fatal when transformation by default.
  70      */
  71     private static final int TEMPLATES_EXPECTED_TYPE = TYPE_FATALERROR;
  72 
  73     /**
  74      * Expect warning when transformation by default.
  75      */
  76     private static final int TRANSFORM_EXPECTED_TYPE = TYPE_WARNING;
  77 
  78     /**
  79      * Data provide provides test XML, stylesheet and output files name.
  80      * @return an array has XML, stylesheet and output files name.
  81      */
  82     @DataProvider
  83     public Object[][] testFiles(){
  84         return new Object[][]{
  85             {XML_DIR + "ErrorListenerTest.xml", 
  86                 XML_DIR + "ErrorListenerTest.xsl",
  87                 GOLDEN_DIR + "ErrorListenerTest.out"}
  88         };
  89     }
  90 
  91     /**
  92      * TransformerFactory Set/Get ErrorListener test.
  93      * 
  94      * @param xmlFile XML test file name.
  95      * @param xslFile XSLT test file name.
  96      * @param goldFile golden file name.
  97      * @throws IOException if any I/O operation error.
  98      * @throws TransformerException If an unrecoverable error occurs during the 
  99      *         course of the transformation. 
 100      */
 101     @Test(dataProvider = "testFiles")
 102     public void testCase1(String xmlFile, String xslFile, String goldFile) 
 103             throws IOException, TransformerException {
 104         String outputFile = getNextFile(this.getClass());
 105  
 106         CheckingErrorListener chkErrorListener = new CheckingErrorListener(THROW_NEVER);
 107 
 108         TransformerFactory factory = TransformerFactory.newInstance();
 109         // Set the errorListener and validate it
 110         factory.setErrorListener(chkErrorListener);
 111 
 112         // Attempt to build templates from known-bad stylesheet
 113         // Validate known errors in stylesheet building
 114         chkErrorListener.setExpected(TEMPLATES_EXPECTED_TYPE,
 115                 ITEM_CHECKFAIL);
 116         Templates templates = factory.newTemplates(new StreamSource(filenameToURL(xslFile)));
 117         // Clear out any setExpected or counters
 118         chkErrorListener.reset();
 119 
 120         // This stylesheet will still work, even though errors
 121         //  were detected during it's building.  Note that
 122         //  future versions of Xalan or other processors may
 123         //  not be able to continue here...
 124         Transformer transformer = templates.newTransformer();
 125 
 126         // Set the errorListener and validate it
 127         transformer.setErrorListener(chkErrorListener);
 128 
 129         // Validate the first xsl:message call in the stylesheet
 130         chkErrorListener.setExpected(TRANSFORM_EXPECTED_TYPE,
 131                 ITEM_CHECKFAIL);
 132         transformer.transform(new StreamSource(filenameToURL(xmlFile)),
 133                 new StreamResult(outputFile));
 134         // Clear out any setExpected or counters
 135         chkErrorListener.reset();
 136         compareWithGold(goldFile, outputFile);
 137     }
 138 
 139     /**
 140      * Build a bad style-sheet/do a transform with DOMs. Verify that the 
 141      * ErrorListener is called properly. Primarily using SAXSources.
 142      * 
 143      * @param xmlFile test XML filename.
 144      * @param xslFile test style-sheet filename.
 145      * @param goldFile golden verification filename.
 146      *  
 147      * @throws TransformerConfigurationException Thrown in case of 
 148      *         ServiceConfigurationError service configuration error or if the
 149      *         implementation is not available or cannot be instantiated.
 150      * @throws IOException if any I/O operation error.
 151      * @throws SAXException for SAX error.
 152      * @throws ParserConfigurationException if  the implementation is not 
 153      *         available or cannot be instantiated. 
 154      */
 155     @Test(dataProvider = "testFiles")
 156     public void testCase2(String xmlFile, String xslFile, String goldFile) 
 157             throws SAXException, ParserConfigurationException, 
 158             TransformerConfigurationException, IOException {
 159         String outputFile = getNextFile(this.getClass());
 160 
 161         CheckingErrorListener loggingErrorListener = new CheckingErrorListener(THROW_NEVER);
 162         // assumes SAXSource.feature!
 163         SAXTransformerFactory saxFactory = (SAXTransformerFactory)TransformerFactory.newInstance();
 164 
 165         // Set the errorListener and validate it
 166         saxFactory.setErrorListener(loggingErrorListener);
 167 
 168         // Use the JAXP way to get an XMLReader
 169         XMLReader reader = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
 170         InputSource is = new InputSource(filenameToURL(xslFile));
 171 
 172         // Attempt to build templates from known-bad stylesheet
 173         // Validate known errors in stylesheet building
 174         loggingErrorListener.setExpected(TEMPLATES_EXPECTED_TYPE,
 175                 ITEM_CHECKFAIL);
 176         TransformerHandler handler = saxFactory.newTransformerHandler(new SAXSource(is));
 177         // Clear out any setExpected or counters
 178         loggingErrorListener.reset();
 179 
 180         // This stylesheet will still work, even though errors
 181         //  were detected during it's building.  Note that
 182         //  future versions of Xalan or other processors may
 183         //  not be able to continue here...
 184 
 185         // Create a result and setup SAX parsing 'tree'
 186         Result result = new StreamResult(outputFile);
 187         handler.setResult(result);
 188         reader.setContentHandler(handler);
 189 
 190         CheckingSAXErrorHandler loggingSAXErrorHandler 
 191                 = new CheckingSAXErrorHandler(CheckingSAXErrorHandler.THROW_NEVER);
 192         reader.setErrorHandler(loggingSAXErrorHandler);
 193 
 194         // Validate the first xsl:message call in the stylesheet
 195         loggingErrorListener.setExpected(TRANSFORM_EXPECTED_TYPE,
 196                 ITEM_CHECKFAIL);
 197         reader.parse(filenameToURL(xmlFile));
 198         // Clear out any setExpected or counters
 199         loggingErrorListener.reset();
 200         loggingSAXErrorHandler.reset();
 201         compareWithGold(goldFile, outputFile);
 202     }
 203     
 204     /**
 205      * Build a bad style-sheet/do a transform with DOMs. Verify that the 
 206      * ErrorListener is called properly. Primarily using DOMSources.
 207      * 
 208      * @param xmlFile test XML filename.
 209      * @param xslFile test style-sheet filename.
 210      * @param goldFile golden verification filename. 
 211      * @throws TransformerConfigurationException Thrown in case of 
 212      *         ServiceConfigurationError service configuration error or if the
 213      *         implementation is not available or cannot be instantiated.
 214      * @throws IOException if any I/O operation error.
 215      * @throws SAXException for SAX error.
 216      * @throws ParserConfigurationException if  the implementation is not 
 217      *         available or cannot be instantiated. 
 218      */
 219     @Test(dataProvider = "testFiles")
 220     public void testCase3(String xmlFile, String xslFile, String goldFile) 
 221             throws ParserConfigurationException, SAXException, IOException, 
 222             TransformerException {
 223         String outputFile = getNextFile(this.getClass());
 224         CheckingErrorListener chkErrorListener = new CheckingErrorListener(THROW_NEVER);
 225         // Startup a DOM factory, create some nodes/DOMs
 226         DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 227         dfactory.setNamespaceAware(true);
 228         DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
 229         Node xslNode = docBuilder.parse(new InputSource(filenameToURL(xslFile)));
 230         Node xmlNode = docBuilder.parse(new InputSource(filenameToURL(xmlFile)));
 231 
 232         // Create a transformer factory with an error listener
 233         TransformerFactory factory = TransformerFactory.newInstance();
 234         factory.setErrorListener(chkErrorListener);
 235 
 236         // Attempt to build templates from known-bad stylesheet
 237         // Validate known errors in stylesheet building
 238         Templates templates = factory.newTemplates(new DOMSource(xslNode));
 239         // Clear out any setExpected or counters 
 240         Transformer transformer = templates.newTransformer();
 241         transformer.setErrorListener(chkErrorListener);
 242         transformer.transform(new DOMSource(xmlNode), new StreamResult(outputFile));
 243         compareWithGold(goldFile, outputFile);
 244     }
 245 }