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.sax;
  21 
  22 import java.io.FileOutputStream;
  23 import java.io.FilePermission;
  24 import java.io.IOException;
  25 import javax.xml.parsers.DocumentBuilder;
  26 import javax.xml.parsers.DocumentBuilderFactory;
  27 import javax.xml.parsers.ParserConfigurationException;
  28 import javax.xml.transform.Result;
  29 import javax.xml.transform.Templates;
  30 import javax.xml.transform.Transformer;
  31 import javax.xml.transform.TransformerConfigurationException;
  32 import javax.xml.transform.TransformerException;
  33 import javax.xml.transform.TransformerFactory;
  34 import javax.xml.transform.dom.DOMSource;
  35 import javax.xml.transform.sax.SAXResult;
  36 import javax.xml.transform.sax.SAXTransformerFactory;
  37 import javax.xml.transform.sax.TransformerHandler;
  38 import javax.xml.transform.stream.StreamResult;
  39 import javax.xml.transform.stream.StreamSource;
  40 import jaxp.library.JAXPBaseTest;
  41 import static jaxp.library.JAXPTestUtilities.CLASS_DIR;
  42 import static jaxp.library.JAXPTestUtilities.compareWithGold;
  43 import static jaxp.library.JAXPTestUtilities.filenameToURL;
  44 import static org.apache.qetest.trax.TraxConst.GOLDEN_DIR;
  45 import static org.apache.qetest.trax.TraxConst.XML_DIR;
  46 import org.apache.qetest.xsl.CheckingContentHandler;
  47 import org.apache.qetest.xsl.CheckingLexicalHandler;
  48 import static org.testng.Assert.assertEquals;
  49 import static org.testng.Assert.assertNull;
  50 import static org.testng.Assert.assertSame;
  51 import static org.testng.Assert.fail;
  52 import org.testng.annotations.AfterGroups;
  53 import org.testng.annotations.BeforeGroups;
  54 import org.testng.annotations.Test;
  55 import org.w3c.dom.Node;
  56 import org.xml.sax.ContentHandler;
  57 import org.xml.sax.InputSource;
  58 import org.xml.sax.SAXException;
  59 import org.xml.sax.ext.LexicalHandler;
  60 
  61 /**
  62  * API Coverage test for the SAXResult class of TRAX.
  63  */
  64 public class SAXResultAPITest extends JAXPBaseTest {
  65 
  66     /**
  67      * Nonsense systemId for various tests.
  68      */
  69     private static final String NONSENSE_SYSTEMID = "file:///nonsense-system-id";
  70 
  71     /**
  72      * Basic API coverage, constructor and set/get methods.
  73      *
  74      * @throws TransformerConfigurationException Thrown in case of 
  75      *         ServiceConfigurationError service configuration error or if the
  76      *         implementation is not available or cannot be instantiated.
  77      */
  78     @Test
  79     public void testCase1() throws TransformerConfigurationException {
  80 
  81         // Default no-arg ctor sets nothing
  82         SAXResult defaultSAX = new SAXResult();
  83         assertNull(defaultSAX.getHandler());
  84         assertNull(defaultSAX.getLexicalHandler());
  85         assertNull(defaultSAX.getSystemId());
  86 
  87         SAXTransformerFactory saxFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
  88         // ctor(Handler) with identity transformer, which is both
  89         //  a ContentHandler and LexicalHandler  
  90         ContentHandler handler = (ContentHandler) saxFactory.newTransformerHandler();
  91         SAXResult handlerSAX = new SAXResult(handler);
  92         assertSame(handlerSAX.getHandler(), handler);
  93         assertNull(handlerSAX.getLexicalHandler());
  94         assertNull(handlerSAX.getSystemId());
  95 
  96         // ctor(Handler) with LoggingContentHandler, which not
  97         //  a LexicalHandler, so it can't be cast
  98         ContentHandler nonLexHandler = new CheckingContentHandler();
  99         SAXResult otherHandlerSAX = new SAXResult(nonLexHandler);
 100         assertSame(otherHandlerSAX.getHandler(), nonLexHandler);
 101         assertNull(otherHandlerSAX.getLexicalHandler());
 102         assertNull(otherHandlerSAX.getSystemId());
 103 
 104         // Note the Javadoc in SAXResult which talks about
 105         //  automatically casting the ContentHandler into
 106         //  a LexicalHandler: this cannot be tested alone
 107         //  here, since it's the Transformer that does that
 108         //  internally if necessary, and it may not get set
 109         //  back into the SAXResult object itself
 110         // set/getHandler API coverage
 111         SAXResult wackySAX = new SAXResult();
 112         wackySAX.setHandler(handler); // isa LexicalHandler also
 113         assertSame(wackySAX.getHandler(), handler);
 114         assertNull(wackySAX.getLexicalHandler());
 115 
 116         // set/getLexicalHandler API coverage
 117         LexicalHandler lexHandler = new CheckingLexicalHandler();
 118         wackySAX.setLexicalHandler(lexHandler); // SCUU4SPPMV - does not work
 119         assertSame(wackySAX.getLexicalHandler(), lexHandler);
 120         assertSame(wackySAX.getHandler(), handler);
 121 
 122         // set/getHandler API coverage, setting to null, which
 123         //  should work here but can't be used legally
 124         wackySAX.setHandler(null);
 125         assertNull(wackySAX.getHandler());
 126         assertSame(wackySAX.getLexicalHandler(), lexHandler);
 127 
 128         wackySAX.setLexicalHandler(null);
 129         assertNull(wackySAX.getLexicalHandler());
 130 
 131         // set/getSystemId API coverage
 132         wackySAX.setSystemId(NONSENSE_SYSTEMID);
 133         assertEquals(wackySAX.getSystemId(), NONSENSE_SYSTEMID);
 134         wackySAX.setSystemId(null);
 135         assertNull(wackySAX.getSystemId());
 136 
 137     }
 138     
 139     /**
 140      * Save system property for restoring.
 141      */
 142     @BeforeGroups (groups = {"readLocalFiles"})
 143     public void setFilePermissions() {
 144         setPermissions(new FilePermission(XML_DIR + "/-", "read"),
 145                 new FilePermission(GOLDEN_DIR + "/-", "read"),
 146                 new FilePermission(CLASS_DIR + "-", "read, write"));
 147     }
 148     
 149     /**
 150      * Restore the system property.
 151      */
 152     @AfterGroups (groups = {"readLocalFiles"})
 153     public void restoreFilePermissions() {
 154         setPermissions();
 155     }
 156 
 157     /**
 158      * Basic functionality of SAXResults.
 159      * @throws TransformerException If an unrecoverable error occurs during the 
 160      *         course of the transformation.
 161      * @throws IOException if any I/O operation error.
 162      */
 163     @Test(groups = {"readLocalFiles"})
 164     public void testCase2() throws TransformerException, IOException {
 165         String xslFile = XML_DIR + "SAXTest.xsl";
 166         String xmlFile = XML_DIR + "SAXTest.xml";
 167         String goldFile = GOLDEN_DIR + "SAXTest.out";
 168         String outputFile = CLASS_DIR + "SAXTest_02.out";
 169         try (FileOutputStream fos = new FileOutputStream(outputFile)) {
 170             SAXTransformerFactory saxFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
 171             Templates streamTemplates = saxFactory.newTemplates(new StreamSource(filenameToURL(xslFile)));
 172             // Use a TransformerHandler for serialization: this
 173             //  supports ContentHandler and can replace the
 174             //  Xalan/Xerces specific Serializers we used to use
 175             TransformerHandler tHandler = saxFactory.newTransformerHandler();
 176             tHandler.setResult(new StreamResult(fos));
 177             SAXResult saxResult = new SAXResult(tHandler);
 178 
 179             // Just do a normal transform to this result
 180             Transformer transformer = streamTemplates.newTransformer();
 181             transformer.transform(new StreamSource(filenameToURL(xmlFile)), saxResult);
 182         }
 183         compareWithGold(goldFile, outputFile);
 184     }
 185 
 186     /**
 187      * Detailed functionality of SAXResults: setLexicalHandler.
 188      *
 189      * @throws IOException if any I/O operation error.
 190      * @throws TransformerException If an unrecoverable error occurs during the 
 191      *         course of the transformation.
 192      * @throws ParserConfigurationException if  the implementation is not 
 193      *         available or cannot be instantiated.
 194      * @throws SAXException for SAX error.
 195      */
 196     @Test(groups = {"readLocalFiles"})
 197     public void testCase3() throws IOException, TransformerException,
 198             ParserConfigurationException, SAXException {
 199         String xslFile = XML_DIR + "SAXdtd.xsl";
 200         String xmlFile = XML_DIR + "SAXdtd.xml";
 201         String goldFile = GOLDEN_DIR + "SAXdtd.out";
 202         String outputFile = CLASS_DIR + "SAXdtd.out";
 203 
 204         try (FileOutputStream fos = new FileOutputStream(outputFile)) {
 205             SAXTransformerFactory saxFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
 206             Templates streamTemplates = saxFactory.newTemplates(new StreamSource(filenameToURL(xslFile)));
 207             TransformerHandler tHandler = saxFactory.newTransformerHandler();
 208             tHandler.setResult(new StreamResult(fos));
 209 
 210             SAXResult saxResult = new SAXResult();
 211             // Add a contentHandler that logs out info about the transform, and
 212             // that passes-through calls back to the original tHandler.
 213             CheckingContentHandler lch = new CheckingContentHandler();
 214             lch.setDefaultHandler(tHandler);
 215             saxResult.setHandler(lch);
 216 
 217             // Add a lexicalHandler that logs out info about the  transform, and
 218             // that passes-through calls back to the original tHandler
 219             CheckingLexicalHandler llh = new CheckingLexicalHandler(tHandler);
 220             saxResult.setLexicalHandler(llh);
 221 
 222             // Just do a normal transform to this result
 223             Transformer transformer = streamTemplates.newTransformer();
 224             transformer.transform(new StreamSource(filenameToURL(xmlFile)), saxResult);
 225             fail("Excepted a TransformerException");
 226         } catch (TransformerException expected) {}
 227         compareWithGold(goldFile, outputFile);
 228 
 229         try (FileOutputStream fos = new FileOutputStream(outputFile)) {
 230             SAXTransformerFactory saxFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
 231             TransformerHandler tHandler = saxFactory.newTransformerHandler();
 232             Result realResult = new StreamResult(fos);
 233             tHandler.setResult(realResult);
 234 
 235             SAXResult saxResult = new SAXResult();
 236             CheckingContentHandler lch = new CheckingContentHandler();
 237             lch.setDefaultHandler(tHandler);
 238             saxResult.setHandler(lch);
 239 
 240             CheckingLexicalHandler llh = new CheckingLexicalHandler(tHandler);
 241             saxResult.setLexicalHandler(llh);
 242 
 243             // Do an identityTransform to this result
 244             Transformer identityTransformer = TransformerFactory.newInstance().newTransformer();
 245             identityTransformer.transform(new StreamSource(filenameToURL(xmlFile)), saxResult);
 246             fail("Excepted a TransformerException");
 247         } catch (TransformerException expected) {}
 248         compareWithGold(goldFile, outputFile);
 249 
 250         try (FileOutputStream fos = new FileOutputStream(outputFile)) {
 251             // Validate a DOMSource to a logging SAXResult, as above
 252             DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 253             dfactory.setNamespaceAware(true);
 254             DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
 255             Node xmlNode = docBuilder.parse(new InputSource(filenameToURL(xmlFile)));
 256             SAXTransformerFactory saxFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
 257 
 258             // Have an actual handler that does the physical output
 259             TransformerHandler tHandler = saxFactory.newTransformerHandler();
 260             Templates streamTemplates = saxFactory.newTemplates(new StreamSource(filenameToURL(xslFile)));
 261             tHandler.setResult(new StreamResult(fos));
 262 
 263             SAXResult saxResult = new SAXResult();
 264             // Add a contentHandler that logs out info about the
 265             //  transform, and that passes-through calls back
 266             //  to the original tHandler
 267             CheckingContentHandler lch = new CheckingContentHandler();
 268             lch.setDefaultHandler(tHandler);
 269             saxResult.setHandler(lch);
 270 
 271             // Add a lexicalHandler that logs out info about the
 272             //  transform, and that passes-through calls back
 273             //  to the original tHandler
 274             CheckingLexicalHandler llh = new CheckingLexicalHandler(tHandler);
 275             saxResult.setLexicalHandler(llh);
 276 
 277             // Just do a normal transform to this result
 278             streamTemplates.newTransformer().transform(new DOMSource(xmlNode), saxResult);
 279             fail("Excepted a TransformerException");
 280         } catch (TransformerException expected) {}
 281         compareWithGold(goldFile, outputFile);
 282     }
 283 
 284     /**
 285      * Negative test: SAXResult without a handler throws TransformerException.
 286      *
 287      * @throws TransformerException If an unrecoverable error occurs during the 
 288      *         course of the transformation.
 289      */
 290     @Test(expectedExceptions = TransformerException.class)
 291     public void negativeTransform() throws TransformerException {
 292         setPermissions(new FilePermission(XML_DIR + "/-", "read"));
 293         String xslFile = XML_DIR + "SAXTest.xsl";
 294         String xmlFile = XML_DIR + "SAXTest.xml";
 295         SAXTransformerFactory saxFactory = (SAXTransformerFactory) TransformerFactory.newInstance();
 296         Templates streamTemplates = saxFactory.newTemplates(new StreamSource(filenameToURL(xslFile)));
 297         // Just do a normal transform to this result
 298         Transformer transformer = streamTemplates.newTransformer();
 299         transformer.transform(new StreamSource(filenameToURL(xmlFile)), new SAXResult());
 300         setPermissions();
 301     }
 302 }