1 /* 2 * Copyright (c) 2014, 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 transform; 25 26 import java.io.BufferedReader; 27 import java.io.ByteArrayInputStream; 28 import java.io.File; 29 import java.io.FileReader; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.io.StringReader; 33 import java.io.StringWriter; 34 35 import javax.xml.transform.Transformer; 36 import javax.xml.transform.TransformerException; 37 import javax.xml.transform.TransformerFactory; 38 import javax.xml.transform.dom.DOMResult; 39 import javax.xml.transform.sax.SAXSource; 40 import javax.xml.transform.stream.StreamResult; 41 import javax.xml.transform.stream.StreamSource; 42 43 import jaxp.library.JAXPTestUtilities; 44 45 import org.testng.Assert; 46 import org.testng.AssertJUnit; 47 import org.testng.annotations.Listeners; 48 import org.testng.annotations.Test; 49 import org.w3c.dom.Document; 50 import org.w3c.dom.Node; 51 import org.w3c.dom.NodeList; 52 import org.xml.sax.ContentHandler; 53 import org.xml.sax.DTDHandler; 54 import org.xml.sax.EntityResolver; 55 import org.xml.sax.ErrorHandler; 56 import org.xml.sax.InputSource; 57 import org.xml.sax.SAXException; 58 import org.xml.sax.SAXNotRecognizedException; 59 import org.xml.sax.SAXNotSupportedException; 60 import org.xml.sax.XMLReader; 61 import org.xml.sax.helpers.AttributesImpl; 62 63 import com.sun.org.apache.xml.internal.serialize.OutputFormat; 64 import com.sun.org.apache.xml.internal.serialize.XMLSerializer; 65 66 /* 67 * @summary Transformer Tests 68 * @bug 6272879 6305029 6505031 8150704 69 */ 70 @Listeners({jaxp.library.FilePolicy.class}) 71 public class TransformerTest { 72 private Transformer createTransformer() throws TransformerException { 73 return TransformerFactory.newInstance().newTransformer(); 74 } 75 76 private Transformer createTransformerFromInputstream(InputStream xslStream) throws TransformerException { 77 return TransformerFactory.newInstance().newTransformer(new StreamSource(xslStream)); 78 } 79 80 private Transformer createTransformerFromResource(String xslResource) throws TransformerException { 81 return TransformerFactory.newInstance().newTransformer(new StreamSource(getClass().getResource(xslResource).toString())); 82 } 83 84 private Document transformInputStreamToDocument(Transformer transformer, InputStream sourceStream) throws TransformerException { 85 DOMResult response = new DOMResult(); 86 transformer.transform(new StreamSource(sourceStream), response); 87 return (Document)response.getNode(); 88 } 89 90 private StringWriter transformResourceToStringWriter(Transformer transformer, String xmlResource) throws TransformerException { 91 StringWriter sw = new StringWriter(); 92 transformer.transform(new StreamSource(getClass().getResource(xmlResource).toString()), new StreamResult(sw)); 93 return sw; 94 } 95 96 /** 97 * Reads the contents of the given file into a string. 98 * WARNING: this method adds a final line feed even if the last line of the file doesn't contain one. 99 * 100 * @param f 101 * The file to read 102 * @return The content of the file as a string, with line terminators as \"n" 103 * for all platforms 104 * @throws IOException 105 * If there was an error reading 106 */ 107 private String getFileContentAsString(File f) throws IOException { 108 try (BufferedReader reader = new BufferedReader(new FileReader(f))) { 109 String line; 110 StringBuilder sb = new StringBuilder(); 111 while ((line = reader.readLine()) != null) { 112 sb.append(line).append("\n"); 113 } 114 return sb.toString(); 115 } 116 } 117 118 private class XMLReaderFor6305029 implements XMLReader { 119 private static final String NAMESPACES = "http://xml.org/sax/features/namespaces"; 120 private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes"; 121 private boolean namespaces = true; 122 private boolean namespacePrefixes = false; 123 private EntityResolver resolver; 124 private DTDHandler dtdHandler; 125 private ContentHandler contentHandler; 126 private ErrorHandler errorHandler; 127 128 public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException { 129 if (name.equals(NAMESPACES)) { 130 return namespaces; 131 } else if (name.equals(NAMESPACE_PREFIXES)) { 132 return namespacePrefixes; 133 } else { 134 throw new SAXNotRecognizedException(); 135 } 136 } 137 138 public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { 139 if (name.equals(NAMESPACES)) { 140 namespaces = value; 141 } else if (name.equals(NAMESPACE_PREFIXES)) { 142 namespacePrefixes = value; 143 } else { 144 throw new SAXNotRecognizedException(); 145 } 146 } 147 148 public Object getProperty(final String name) throws SAXNotRecognizedException, SAXNotSupportedException { 149 return null; 150 } 151 152 public void setProperty(final String name, final Object value) throws SAXNotRecognizedException, SAXNotSupportedException { 153 } 154 155 public void setEntityResolver(final EntityResolver theResolver) { 156 this.resolver = theResolver; 157 } 158 159 public EntityResolver getEntityResolver() { 160 return resolver; 161 } 162 163 public void setDTDHandler(final DTDHandler theHandler) { 164 dtdHandler = theHandler; 165 } 166 167 public DTDHandler getDTDHandler() { 168 return dtdHandler; 169 } 170 171 public void setContentHandler(final ContentHandler handler) { 172 contentHandler = handler; 173 } 174 175 public ContentHandler getContentHandler() { 176 return contentHandler; 177 } 178 179 public void setErrorHandler(final ErrorHandler handler) { 180 errorHandler = handler; 181 } 182 183 public ErrorHandler getErrorHandler() { 184 return errorHandler; 185 } 186 187 public void parse(final InputSource input) throws IOException, SAXException { 188 parse(); 189 } 190 191 public void parse(final String systemId) throws IOException, SAXException { 192 parse(); 193 } 194 195 private void parse() throws SAXException { 196 contentHandler.startDocument(); 197 contentHandler.startPrefixMapping("prefix", "namespaceUri"); 198 199 AttributesImpl atts = new AttributesImpl(); 200 if (namespacePrefixes) { 201 atts.addAttribute("", "xmlns:prefix", "xmlns:prefix", "CDATA", "namespaceUri"); 202 } 203 204 contentHandler.startElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : "", atts); 205 contentHandler.endElement("namespaceUri", "localName", namespacePrefixes ? "prefix:localName" : ""); 206 contentHandler.endPrefixMapping("prefix"); 207 contentHandler.endDocument(); 208 } 209 } 210 211 /* 212 * @bug 6272879 213 * @summary Test for JDK-6272879 214 */ 215 @Test 216 public final void testBug6272879() throws IOException, TransformerException { 217 final String LINE_SEPARATOR = System.getProperty("line.separator"); 218 219 final String xsl = 220 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR + 221 "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">" + LINE_SEPARATOR + 222 "<xsl:output method=\"xml\" indent=\"no\" encoding=\"ISO-8859-1\"/>" + LINE_SEPARATOR + 223 "<xsl:template match=\"/\">" + LINE_SEPARATOR + 224 "<xsl:element name=\"TransformateurXML\">" + LINE_SEPARATOR + 225 " <xsl:for-each select=\"XMLUtils/test\">" + LINE_SEPARATOR + 226 " <xsl:element name=\"test2\">" + LINE_SEPARATOR + 227 " <xsl:element name=\"valeur2\">" + LINE_SEPARATOR + 228 " <xsl:attribute name=\"attribut2\">" + LINE_SEPARATOR + 229 " <xsl:value-of select=\"valeur/@attribut\"/>" + LINE_SEPARATOR + 230 " </xsl:attribute>" + LINE_SEPARATOR + 231 " <xsl:value-of select=\"valeur\"/>" + LINE_SEPARATOR + 232 " </xsl:element>" + LINE_SEPARATOR + 233 " </xsl:element>" + LINE_SEPARATOR + 234 " </xsl:for-each>" + LINE_SEPARATOR + 235 "</xsl:element>" + LINE_SEPARATOR + 236 "</xsl:template>" + LINE_SEPARATOR + 237 "</xsl:stylesheet>"; 238 239 final String sourceXml = 240 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + LINE_SEPARATOR + 241 // "<!DOCTYPE XMLUtils [" + LINE_SEPARATOR + 242 // "<!ELEMENT XMLUtils (test*)>" + LINE_SEPARATOR + 243 // "<!ELEMENT test (valeur*)>" + LINE_SEPARATOR + 244 // "<!ELEMENT valeur (#PCDATA)>" + LINE_SEPARATOR + 245 // "<!ATTLIST valeur attribut CDATA #REQUIRED>]>" + 246 // LINE_SEPARATOR + 247 "<XMLUtils>" + LINE_SEPARATOR + 248 " <test>" + LINE_SEPARATOR + 249 " <valeur attribut=\"Attribut 1\">Valeur 1</valeur>" + LINE_SEPARATOR + 250 " </test>" + LINE_SEPARATOR + 251 " <test>" + LINE_SEPARATOR + 252 " <valeur attribut=\"Attribut 2\">Valeur 2</valeur>" + LINE_SEPARATOR + 253 " </test>" + LINE_SEPARATOR + 254 "</XMLUtils>"; 255 256 Document document; 257 Node node; 258 259 System.out.println("Stylesheet:"); 260 System.out.println("=================================="); 261 System.out.println(xsl); 262 System.out.println(); 263 264 System.out.println("Source file before transformation:"); 265 System.out.println("=================================="); 266 System.out.println(sourceXml); 267 System.out.println(); 268 269 System.out.println("Source file after transformation:"); 270 System.out.println("================================="); 271 document = transformInputStreamToDocument(createTransformerFromInputstream(new ByteArrayInputStream(xsl.getBytes())), 272 new ByteArrayInputStream(sourceXml.getBytes())); 273 OutputFormat format = new OutputFormat(); 274 format.setIndenting(true); 275 new XMLSerializer(System.out, format).serialize(document); 276 System.out.println(); 277 278 System.out.println("Node content for element valeur2:"); 279 System.out.println("================================="); 280 NodeList nodes = document.getElementsByTagName("valeur2"); 281 nodes = document.getElementsByTagName("valeur2"); 282 for (int i = 0; i < nodes.getLength(); i++) { 283 node = nodes.item(i); 284 System.out.println(" Node value: " + node.getFirstChild().getNodeValue()); 285 System.out.println(" Node attribute: " + node.getAttributes().item(0).getNodeValue()); 286 287 AssertJUnit.assertEquals("Node value mismatch", "Valeur " + (i + 1), node.getFirstChild().getNodeValue()); 288 AssertJUnit.assertEquals("Node attribute mismatch", "Attribut " + (i + 1), node.getAttributes().item(0).getNodeValue()); 289 } 290 } 291 292 /* 293 * @bug 6305029 294 * @summary Test for JDK-6305029 295 */ 296 @Test 297 public final void testBug6305029() throws TransformerException { 298 final String XML_DOCUMENT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<prefix:localName xmlns:prefix=\"namespaceUri\"/>"; 299 300 // test SAXSource 301 SAXSource saxSource = new SAXSource(new XMLReaderFor6305029(), new InputSource()); 302 StringWriter resultWriter = new StringWriter(); 303 createTransformer().transform(saxSource, new StreamResult(resultWriter)); 304 AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, resultWriter.toString()); 305 306 // test StreamSource 307 StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); 308 resultWriter = new StringWriter(); 309 createTransformer().transform(streamSource, new StreamResult(resultWriter)); 310 AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, resultWriter.toString()); 311 } 312 313 /* 314 * @bug 6505031 315 * @summary Test transformer parses keys and their values coming from different xml documents. 316 */ 317 @Test 318 public final void testBug6505031() throws TransformerException { 319 Transformer transformer = createTransformerFromResource("transform.xsl"); 320 transformer.setParameter("config", getClass().getResource("config.xml").toString()); 321 transformer.setParameter("mapsFile", getClass().getResource("maps.xml").toString()); 322 String s = transformResourceToStringWriter(transformer, "template.xml").toString(); 323 Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); 324 } 325 326 /* 327 * @bug 8150704 328 * @summary Test that XSL transformation with lots of temporary result trees will not run out of DTM IDs. 329 */ 330 @Test 331 public final void testBug8150704() throws TransformerException, IOException { 332 System.out.println("Testing transformation of Bug8150704-1.xml..."); 333 Transformer transformer = createTransformerFromResource("Bug8150704-1.xsl"); 334 StringWriter result = transformResourceToStringWriter(transformer, "Bug8150704-1.xml"); 335 String resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); 336 String reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-1.ref").getPath())); 337 Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-1.xml does not match reference"); 338 System.out.println("Passed."); 339 340 System.out.println("Testing transformation of Bug8150704-2.xml..."); 341 transformer = createTransformerFromResource("Bug8150704-2.xsl"); 342 result = transformResourceToStringWriter(transformer, "Bug8150704-2.xml"); 343 resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); 344 reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-2.ref").getPath())); 345 Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-2.xml does not match reference"); 346 System.out.println("Passed."); 347 } 348 }