1 /*
   2  * Copyright (c) 2015, 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 com.sun.org.apache.xml.internal.serializer.OutputPropertiesFactory;
  23 import com.sun.org.apache.xml.internal.serializer.Serializer;
  24 import com.sun.org.apache.xml.internal.serializer.SerializerFactory;
  25 import java.io.BufferedInputStream;
  26 import java.io.BufferedReader;
  27 import java.io.File;
  28 import java.io.FileInputStream;
  29 import java.io.FileOutputStream;
  30 import java.io.InputStream;
  31 import java.io.InputStreamReader;
  32 import java.io.Reader;
  33 import java.util.Properties;
  34 import java.util.PropertyPermission;
  35 import javax.xml.parsers.DocumentBuilder;
  36 import javax.xml.parsers.DocumentBuilderFactory;
  37 import javax.xml.parsers.SAXParser;
  38 import javax.xml.parsers.SAXParserFactory;
  39 import javax.xml.transform.OutputKeys;
  40 import javax.xml.transform.Result;
  41 import javax.xml.transform.Templates;
  42 import javax.xml.transform.Transformer;
  43 import javax.xml.transform.TransformerFactory;
  44 import javax.xml.transform.dom.DOMResult;
  45 import javax.xml.transform.dom.DOMSource;
  46 import javax.xml.transform.sax.SAXResult;
  47 import javax.xml.transform.sax.SAXSource;
  48 import javax.xml.transform.sax.SAXTransformerFactory;
  49 import javax.xml.transform.sax.TransformerHandler;
  50 import javax.xml.transform.stream.StreamResult;
  51 import javax.xml.transform.stream.StreamSource;
  52 import jaxp.library.JAXPFileBaseTest;
  53 import static jaxp.library.JAXPTestUtilities.compareWithGold;
  54 import static jaxp.library.JAXPTestUtilities.filenameToURL;
  55 import static org.apache.qetest.trax.TraxConst.GOLDEN_DIR;
  56 import static org.apache.qetest.trax.TraxConst.XML_DIR;
  57 import static jaxp.library.JAXPTestUtilities.getNextFile;
  58 import static org.testng.Assert.*;
  59 import org.testng.annotations.Test;
  60 import org.w3c.dom.Node;
  61 import org.xml.sax.InputSource;
  62 import org.xml.sax.XMLFilter;
  63 import org.xml.sax.XMLReader;
  64 
  65 /**
  66  * Test version of xml-xalan/java/samples/trax/Examples.java.
  67  * This file is essentially copied from the Examples for TRAX, or
  68  * javax.xml.transform; however this file actually validates most output and
  69  * behavior for correctness.
  70  */
  71 public class ExamplesTest extends JAXPFileBaseTest {
  72     /**
  73      * Test XML file 1 name.
  74      */
  75     private static final String SOURCE_ID = XML_DIR + "xml/foo.xml";
  76     
  77     /**
  78      * Test XML file 2 name.
  79      */
  80     private static final String SOURCE_ID2 = XML_DIR + "xml/baz.xml";
  81     
  82     /**
  83      * Test stylesheet file name.
  84      */
  85     private static final String XSL_ID =  XML_DIR + "xsl/foo.xsl";
  86 
  87     /**
  88      * Show the Transformer as a simple XMLFilter. This is pretty similar to
  89      * exampleXMLReader, except that here the parent XMLReader is created by the
  90      * caller, instead of automatically within the XMLFilter. This gives the
  91      * caller more direct control over the parent reader.
  92      *
  93      * @throws Exception If any errors occur.
  94      */
  95     @Test
  96     public void exampleXMLFilter() throws Exception {
  97         String outputFile = getNextFile(this.getClass());
  98         try (FileOutputStream fos = new FileOutputStream(outputFile)) {
  99 
 100             TransformerFactory tfactory = TransformerFactory.newInstance();
 101             SAXParserFactory factory = SAXParserFactory.newInstance();
 102             factory.setNamespaceAware(true);
 103             SAXParser jaxpParser = factory.newSAXParser();
 104             XMLReader reader = jaxpParser.getXMLReader();
 105 
 106             // Set the result handling to be a serialization to the file output stream.
 107             Serializer serializer = SerializerFactory.getSerializer(
 108                     OutputPropertiesFactory.getDefaultMethodProperties("xml"));
 109             serializer.setOutputStream(fos);
 110             reader.setContentHandler(serializer.asContentHandler());
 111             reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
 112                     true);
 113             reader.setFeature("http://apache.org/xml/features/validation/dynamic",
 114                     true);
 115             XMLFilter filter = ((SAXTransformerFactory) tfactory)
 116                     .newXMLFilter(new StreamSource(filenameToURL(XSL_ID)));
 117             filter.setParent(reader);
 118 
 119             // Now, when you call transformer.parse, it will set itself as
 120             // the content handler for the parser object (it's "parent"), and
 121             // will then call the parse method on the parser.
 122             filter.parse(new InputSource(filenameToURL(SOURCE_ID)));
 123         }
 124         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_14.out", outputFile));
 125     }
 126 
 127     /**
 128      * Show simple transformation from reader to output stream. In general this
 129      * use case is discouraged, since the XML encoding can not be processed.
 130      *
 131      * @throws Exception If any errors occur.
 132      */
 133     @Test
 134     public void exampleFromReader() throws Exception {
 135         String outputFile = getNextFile(this.getClass());
 136         // Create a transform factory instance.
 137         TransformerFactory tfactory = TransformerFactory.newInstance();
 138 
 139         // Note that in this case the XML encoding can not be processed!
 140         Reader xslReader = new BufferedReader(new InputStreamReader(new FileInputStream(XSL_ID), "UTF-8"));
 141         StreamSource xslSource = new StreamSource(xslReader);
 142         // Note that if we don't do this, relative URLs can not be resolved correctly!
 143         xslSource.setSystemId(filenameToURL(XSL_ID));
 144 
 145         // Create a transformer for the stylesheet.
 146         Transformer transformer = tfactory.newTransformer(xslSource);
 147 
 148         Reader xmlReader = new BufferedReader(new InputStreamReader(new FileInputStream(SOURCE_ID), "UTF-8"));
 149         StreamSource xmlSource = new StreamSource(xmlReader);
 150         // Note that if we don't do this, relative URLs can not be resolved correctly!
 151         xmlSource.setSystemId(filenameToURL(SOURCE_ID));
 152 
 153         // Transform the source XML to output file.
 154         transformer.transform(xmlSource, new StreamResult(outputFile));
 155         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_5.out", outputFile));
 156     }
 157 
 158     /**
 159      * Show the Transformer using SAX events in and SAX events out.
 160      *
 161      * @throws Exception If any errors occur.
 162      */
 163     @Test
 164     public void exampleContentHandlerToContentHandler() throws Exception {
 165         TransformerFactory tfactory = TransformerFactory.newInstance();
 166         String outputFile = getNextFile(this.getClass());
 167         try (FileOutputStream fos = new FileOutputStream(outputFile)) {
 168             // Does this factory support SAX features?
 169             if (!tfactory.getFeature(SAXSource.FEATURE)) {
 170                 return;
 171             }
 172             // If so, we can safely cast.
 173             SAXTransformerFactory stfactory = (SAXTransformerFactory) tfactory;
 174 
 175             // A TransformerHandler is a ContentHandler that will listen for
 176             // SAX events, and transform them to the result.
 177             TransformerHandler handler
 178                     = stfactory.newTransformerHandler(new StreamSource(filenameToURL(XSL_ID)));
 179 
 180             // Set the result handling to be a serialization to the file output stream.
 181             Serializer serializer = SerializerFactory.getSerializer(
 182                     OutputPropertiesFactory.getDefaultMethodProperties("xml"));
 183             serializer.setOutputStream(fos);
 184             Result result = new SAXResult(serializer.asContentHandler());
 185 
 186             handler.setResult(result);
 187             SAXParserFactory factory = SAXParserFactory.newInstance();
 188             factory.setNamespaceAware(true);
 189             XMLReader reader = factory.newSAXParser().getXMLReader();
 190             reader.setContentHandler(handler);
 191 
 192             // It's a good idea for the parser to send lexical events.
 193             // The TransformerHandler is also a LexicalHandler.
 194             reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
 195 
 196             // Parse the source XML, and send the parse events to the TransformerHandler.
 197             reader.parse(filenameToURL(SOURCE_ID));
 198         }
 199         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_3.out", outputFile));
 200     }
 201 
 202     /**
 203      * Show the Transformer using SAX events in and DOM nodes out.
 204      *
 205      * @throws Exception If any errors occur.
 206      */
 207     @Test
 208     public void exampleContentHandler2DOM() throws Exception {
 209         String outputFile = getNextFile(this.getClass());
 210         TransformerFactory tfactory = TransformerFactory.newInstance();
 211 
 212         // Make sure the transformer factory we obtained supports both
 213         // DOM and SAX.
 214         if (!(tfactory.getFeature(SAXSource.FEATURE)
 215                 && tfactory.getFeature(DOMSource.FEATURE))) {
 216             return;
 217         }
 218         // We can now safely cast to a SAXTransformerFactory.
 219         SAXTransformerFactory sfactory = (SAXTransformerFactory) tfactory;
 220 
 221         // Create an Document node as the root for the output.
 222         DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 223         DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
 224         org.w3c.dom.Document outNode = docBuilder.newDocument();
 225 
 226         // Create a ContentHandler that can liston to SAX events
 227         // and transform the output to DOM nodes.
 228         TransformerHandler handler
 229                 = sfactory.newTransformerHandler(new StreamSource(filenameToURL(XSL_ID)));
 230         handler.setResult(new DOMResult(outNode));
 231 
 232         SAXParserFactory factory = SAXParserFactory.newInstance();
 233         factory.setNamespaceAware(true);
 234         XMLReader reader = factory.newSAXParser().getXMLReader();
 235         reader.setContentHandler(handler);
 236         reader.setProperty("http://xml.org/sax/properties/lexical-handler",
 237                 handler);
 238 
 239         // Send the SAX events from the parser to the transformer,
 240         // and thus to the DOM tree.
 241         reader.parse(filenameToURL(SOURCE_ID));
 242 
 243         // Serialize the node for diagnosis.
 244         //    This serializes to outNames.nextName()
 245         Transformer serializer = tfactory.newTransformer();
 246         serializer.setOutputProperty(OutputKeys.INDENT, "yes");
 247         serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
 248         serializer.transform(new DOMSource(outNode),
 249                 new StreamResult(outputFile));
 250         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_2.out", outputFile));
 251     }
 252 
 253     /**
 254      * A fuller example showing how the TrAX interface can be used to serialize
 255      * a DOM tree.
 256      *
 257      * @throws Exception If any errors occur.
 258      */
 259     @Test
 260     public void exampleAsSerializer() throws Exception {
 261         String outputFile = getNextFile(this.getClass());
 262         DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 263         DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
 264         org.w3c.dom.Document outNode = docBuilder.newDocument();
 265         Node doc = docBuilder.parse(new InputSource(filenameToURL(SOURCE_ID)));
 266 
 267         TransformerFactory tfactory = TransformerFactory.newInstance();
 268 
 269         // This creates a transformer that does a simple identity transform,
 270         // and thus can be used for all intents and purposes as a serializer.
 271         Transformer serializer = tfactory.newTransformer();
 272 
 273         Properties oprops = new Properties();
 274         oprops.put("method", "html");
 275         oprops.put("{http://xml.apache.org/xslt}indent-amount", "2");
 276         serializer.setOutputProperties(oprops);
 277         serializer.transform(new DOMSource(doc),
 278                 new StreamResult(outputFile));
 279         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_1.out", outputFile));
 280     }
 281 
 282     /**
 283      * Show simple transformation from input stream to output stream.
 284      *
 285      * @throws Exception If any errors occur.
 286      */
 287     @Test
 288     public void exampleFromStream() throws Exception {
 289         String outputFile = getNextFile(this.getClass());
 290         try (InputStream xslIS = new BufferedInputStream(new FileInputStream(XSL_ID));
 291                 InputStream xmlIS = new BufferedInputStream(new FileInputStream(SOURCE_ID))) {
 292             // Create a transform factory instance.
 293             TransformerFactory tfactory = TransformerFactory.newInstance();
 294             StreamSource xslSource = new StreamSource(xslIS);
 295             // Note that if we don't do this, relative URLs can not be resolved correctly!
 296             xslSource.setSystemId(filenameToURL(XSL_ID));
 297 
 298             // Create a transformer for the stylesheet.
 299             Transformer transformer = tfactory.newTransformer(xslSource);
 300             StreamSource xmlSource = new StreamSource(xmlIS);
 301             // Note that if we don't do this, relative URLs can not be resolved correctly!
 302             xmlSource.setSystemId(filenameToURL(SOURCE_ID));
 303 
 304             // Transform the source XML to output file.
 305             transformer.transform(xmlSource, new StreamResult(outputFile));
 306         }
 307         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_6.out", outputFile));
 308     }
 309 
 310     /**
 311      * Show how to override output properties.
 312      *
 313      * @throws Exception If any errors occur.
 314      */
 315     @Test
 316     public void exampleOutputProperties() throws Exception {
 317         String outputFile = getNextFile(this.getClass());
 318 
 319         TransformerFactory tfactory = TransformerFactory.newInstance();
 320         Templates templates = tfactory.newTemplates(new StreamSource(filenameToURL(XSL_ID)));
 321         Properties oprops = templates.getOutputProperties();
 322 
 323         oprops.put(OutputKeys.INDENT, "yes");
 324 
 325         Transformer transformer = templates.newTransformer();
 326 
 327         transformer.setOutputProperties(oprops);
 328         transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)),
 329                 new StreamResult(outputFile));
 330         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_7.out", outputFile));
 331     }
 332 
 333     /**
 334      * Show how to transform a DOM tree into another DOM tree. This uses the
 335      * javax.xml.parsers to parse an XML file into a DOM, and create an output
 336      * DOM.
 337      *
 338      * @throws Exception If any errors occur.
 339      */
 340     public void exampleDOM2DOM() throws Exception {
 341         String outputFile = getNextFile(this.getClass());
 342         TransformerFactory tfactory = TransformerFactory.newInstance();
 343 
 344         DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
 345         dfactory.setNamespaceAware(true);
 346         DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
 347         org.w3c.dom.Document outNode = docBuilder.newDocument();
 348         Node xslDoc = docBuilder.parse(new InputSource(filenameToURL(XSL_ID)));
 349         DOMSource dsource = new DOMSource(xslDoc);
 350         // If we don't do this, the transformer won't know how to
 351         // resolve relative URLs in the stylesheet.
 352         dsource.setSystemId(filenameToURL(XSL_ID));
 353 
 354         Templates templates = tfactory.newTemplates(dsource);
 355 
 356         Transformer transformer = templates.newTransformer();
 357         Node xmlDoc = docBuilder.parse(new InputSource(filenameToURL(SOURCE_ID)));
 358 
 359         transformer.transform(new DOMSource(xmlDoc), new DOMResult(outNode));
 360 
 361         Transformer serializer = tfactory.newTransformer();
 362         serializer.transform(new DOMSource(outNode), new StreamResult(outputFile));
 363         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_4.out", outputFile));
 364     }
 365 
 366     /**
 367      * Show the Transformer using SAX events in and DOM nodes out.
 368      * 
 369      * @throws Exception If any errors occur.
 370      */
 371     @Test
 372     public void exampleSimple1() throws Exception {        
 373         String outputFile = getNextFile(this.getClass());
 374         // Create a transform factory instance.
 375         TransformerFactory tfactory = TransformerFactory.newInstance();
 376 
 377         // Create a transformer for the stylesheet.
 378         Transformer transformer
 379                 = tfactory.newTransformer(new StreamSource(filenameToURL(XSL_ID)));
 380         // No need to setSystemId, the transformer can get it from the URL
 381 
 382         transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)),
 383                 new StreamResult(outputFile));
 384         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_8.out", outputFile));
 385     }
 386 
 387     /**
 388      * Show the simplest possible transformation from File to a File.
 389      *
 390      * @throws Exception If any errors occur.
 391      */
 392     @Test
 393     public void exampleSimple2() throws Exception {
 394         String outputFile = getNextFile(this.getClass());
 395 
 396         TransformerFactory tfactory = TransformerFactory.newInstance();
 397 
 398         // Create a transformer for the stylesheet.
 399         try {
 400             setPermissions(new PropertyPermission("user.dir", "read"));
 401             Transformer transformer
 402                 = tfactory.newTransformer(new StreamSource(new File(XSL_ID)));
 403             // No need to setSystemId, the transformer can get it from the File
 404 
 405             transformer.transform(new StreamSource(new File(SOURCE_ID)),
 406                 new StreamResult(new File(outputFile)));
 407         } finally {
 408             setPermissions();
 409         }
 410         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_9.out", outputFile));
 411     }
 412 
 413     /**
 414      * Show the that a transformer can be reused, and show resetting a parameter
 415      * on the transformer.
 416      *
 417      * @throws Exception If any errors occur.
 418      */
 419     @Test
 420     public void exampleTransformerReuse() throws Exception {
 421         String outputFile = getNextFile(this.getClass());
 422         // Create a transform factory instance.
 423         TransformerFactory tfactory = TransformerFactory.newInstance();
 424 
 425         // Create a transformer for the stylesheet.
 426         Transformer transformer
 427                 = tfactory.newTransformer(new StreamSource(filenameToURL(XSL_ID)));
 428 
 429         transformer.setParameter("a-param", "hello to you!");
 430 
 431         transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)),
 432                 new StreamResult(outputFile));
 433         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_10.out", outputFile));
 434 
 435         transformer.setParameter("a-param",  "hello to me!");
 436         transformer.setOutputProperty(OutputKeys.INDENT, "yes");
 437         String outputFile2 = getNextFile(this.getClass());
 438         transformer.transform(new StreamSource(filenameToURL(SOURCE_ID)),
 439                 new StreamResult(outputFile2));
 440         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_11.out", outputFile));
 441     }
 442 
 443     /**
 444      * Show the simplest possible transformation from system id to output
 445      * stream.
 446      *
 447      * @throws Exception If any errors occur.
 448      */
 449     @Test
 450     public void exampleUseTemplatesObj() throws Exception {
 451         String outputFile1 = getNextFile(this.getClass());
 452         String outputFile2 = getNextFile(this.getClass());
 453         TransformerFactory tfactory = TransformerFactory.newInstance();
 454 
 455         // Create a templates object, which is the processed,
 456         // thread-safe representation of the stylesheet.
 457         Templates templates = tfactory.newTemplates(new StreamSource(filenameToURL(XSL_ID)));
 458 
 459         // Illustrate the fact that you can make multiple transformers
 460         // from the same template.
 461         Transformer transformer1 = templates.newTransformer();
 462         Transformer transformer2 = templates.newTransformer();
 463 
 464         transformer1.transform(new StreamSource(filenameToURL(SOURCE_ID)),
 465                 new StreamResult(outputFile1));
 466         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_12.out", outputFile1));
 467 
 468         transformer2.transform(new StreamSource(filenameToURL(SOURCE_ID2)),
 469                 new StreamResult(outputFile2));
 470         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_13.out", outputFile2));
 471     }
 472 
 473     /**
 474      * Show the Transformer as a SAX2 XMLReader. An XMLFilter obtained from
 475      * newXMLFilter should act as a transforming XMLReader if setParent is not
 476      * called. Internally, an XMLReader is created as the parent for the
 477      * XMLFilter.
 478      * 
 479      * @throws Exception If any errors occur.
 480      */
 481     @Test
 482     public void exampleXMLReader() throws Exception {
 483         String outputFile = getNextFile(this.getClass());
 484         try (FileOutputStream fos = new FileOutputStream(outputFile)) {
 485             TransformerFactory tfactory = TransformerFactory.newInstance();
 486             XMLReader reader  = ((SAXTransformerFactory) tfactory)
 487                     .newXMLFilter(new StreamSource(filenameToURL(XSL_ID)));
 488 
 489             // Set the result handling to be a serialization to the file output stream.
 490             Serializer serializer = SerializerFactory.getSerializer(OutputPropertiesFactory.getDefaultMethodProperties("xml"));
 491 
 492             serializer.setOutputStream(fos);
 493 
 494             reader.setContentHandler(serializer.asContentHandler());
 495             reader.parse(new InputSource(filenameToURL(SOURCE_ID)));
 496         }
 497         assertTrue(compareWithGold(GOLDEN_DIR + "ExamplesTest_15.out", outputFile));
 498     }
 499 }