1 /* 2 * Copyright (c) 2003, 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 package test.gaptest; 24 25 import static jaxp.library.JAXPTestUtilities.filenameToURL; 26 import static org.testng.Assert.assertEquals; 27 import static test.gaptest.GapTestConst.GOLDEN_DIR; 28 import static test.gaptest.GapTestConst.XML_DIR; 29 30 import java.io.IOException; 31 import java.nio.file.Files; 32 import java.nio.file.Paths; 33 34 import javax.xml.transform.Transformer; 35 import javax.xml.transform.TransformerException; 36 import javax.xml.transform.TransformerFactory; 37 import javax.xml.transform.dom.DOMResult; 38 import javax.xml.transform.stream.StreamSource; 39 40 import org.testng.annotations.Listeners; 41 import org.testng.annotations.Test; 42 import org.w3c.dom.NamedNodeMap; 43 import org.w3c.dom.Node; 44 import org.w3c.dom.NodeList; 45 46 /* 47 * @test 48 * @bug 4858685 4894410 49 * @library /javax/xml/jaxp/libs 50 * @run testng/othervm -DrunSecMngr=true test.gaptest.Bug4858685 51 * @run testng/othervm test.gaptest.Bug4858685 52 * @summary test transforming text node 53 */ 54 @Listeners({jaxp.library.FilePolicy.class}) 55 public class Bug4858685 { 56 @Test 57 public void test() throws TransformerException, IOException { 58 String uri = XML_DIR + "certificate.xml"; 59 TransformerFactory transformerFactory = TransformerFactory.newInstance(); 60 61 Transformer transformer = transformerFactory.newTransformer(); 62 63 // use URI as a StreamSource 64 StreamSource streamSource = new StreamSource(filenameToURL(uri)); 65 66 DOMResult domResult = new DOMResult(); 67 68 // StreamSource -> DOMResult 69 transformer.transform(streamSource, domResult); 70 71 // dump DOM in a human readable form 72 String gotString = DOMDump.dumpDom(domResult.getNode()); 73 74 String goldenString = new String(Files.readAllBytes(Paths.get(GOLDEN_DIR + "Bug4858685.txt"))); 75 76 assertEquals(gotString, goldenString); 77 78 } 79 80 /** 81 * DOMDump: dump a DOM to a String in human readable form. method dumpDOM() 82 * is static for easy calling: 83 */ 84 private static class DOMDump { 85 86 /** 87 * the maximum level to indent with blanks 88 */ 89 private static final int BLANKS_LEN = 64; 90 91 /** 92 * each level of the tree will be indented with blanks for readability 93 */ 94 private static final String BLANKS = " "; 95 96 /** 97 * dumpDOM will dump the DOM into a String for human readability 98 * 99 * @param domNode 100 * the DOM Node to dump 101 * @return human readabile DOM as a String 102 */ 103 public static String dumpDom(Node domNode) { 104 return dumpInternal(domNode, 0); 105 } 106 107 /** 108 * dumpInternal is used internaly to recursively dump DOM Nodes 109 * 110 * @param domNode 111 * to dump 112 * @param indent 113 * level 114 * @return domNode as human readable String 115 */ 116 private static String dumpInternal(Node domNode, int indent) { 117 118 String result = ""; 119 120 // indent for readability 121 result += indentBlanks(indent); 122 indent += 2; 123 124 // protect against null 125 if (domNode == null) { 126 result = result + "[null]" + "\n"; 127 return result; 128 } 129 130 // what to output depends on NodeType 131 short type = domNode.getNodeType(); 132 switch (type) { 133 case Node.ATTRIBUTE_NODE: { 134 result += "[attribute] " + domNode.getNodeName() + "=\"" + domNode.getNodeValue() + "\""; 135 break; 136 } 137 case Node.CDATA_SECTION_NODE: { 138 result += "[cdata] " + domNode.getNodeValue(); 139 break; 140 } 141 case Node.COMMENT_NODE: { 142 result += "[comment] " + domNode.getNodeValue(); 143 break; 144 } 145 case Node.DOCUMENT_FRAGMENT_NODE: { 146 result += "[document fragment]"; 147 break; 148 } 149 case Node.DOCUMENT_NODE: { 150 result += "[document]"; 151 break; 152 } 153 case Node.DOCUMENT_TYPE_NODE: { 154 result += "[document type] " + domNode.getNodeName(); 155 break; 156 } 157 case Node.ELEMENT_NODE: { 158 result += "[element] " + domNode.getNodeName(); 159 // output all attributes for Element 160 if (domNode.hasAttributes()) { 161 NamedNodeMap attributes = domNode.getAttributes(); 162 for (int onAttribute = 0; onAttribute < attributes.getLength(); onAttribute++) { 163 164 // seprate each attribute with a space 165 result += " "; 166 167 Node attribute = attributes.item(onAttribute); 168 String namespaceURI = attribute.getNamespaceURI(); 169 String prefix = attribute.getPrefix(); 170 String localName = attribute.getLocalName(); 171 String name = attribute.getNodeName(); 172 String value = attribute.getNodeValue(); 173 174 // using Namespaces? 175 if (namespaceURI != null) { 176 result += "{" + namespaceURI + "}"; 177 } 178 if (prefix != null) { 179 result += prefix + ":"; 180 } 181 182 // name="value" 183 result += attribute.getNodeName() + "=\"" + attribute.getNodeValue() + "\""; 184 } 185 } 186 187 break; 188 } 189 case Node.ENTITY_NODE: { 190 result += "[entity] " + domNode.getNodeName(); 191 break; 192 } 193 case Node.ENTITY_REFERENCE_NODE: { 194 result += "[entity reference] " + domNode.getNodeName(); 195 break; 196 } 197 case Node.NOTATION_NODE: { 198 result += "[notation] " + domNode.getNodeName(); 199 break; 200 } 201 case Node.PROCESSING_INSTRUCTION_NODE: { 202 result += "[pi] target=\"" + domNode.getNodeName() + "\" content=\"" + domNode.getNodeValue() + "\""; 203 break; 204 } 205 case Node.TEXT_NODE: { 206 result += "[text] " + domNode.getNodeValue(); 207 break; 208 } 209 default: { 210 result += "[unknown]"; 211 break; 212 } 213 } 214 215 // humans read in lines 216 result += "\n"; 217 218 // process children 219 NodeList children = domNode.getChildNodes(); 220 for (int onChild = 0; onChild < children.getLength(); onChild++) { 221 Node child = children.item(onChild); 222 result += dumpInternal(child, indent); 223 } 224 225 // return human readable DOM as String 226 return result; 227 } 228 229 /** 230 * indentBlanks will return a String of indent blanks 231 * 232 * @param indent 233 * level 234 * @return String of blanks 235 */ 236 private static String indentBlanks(int indent) { 237 if (indent == 0) { 238 return ""; 239 } 240 241 if (indent > BLANKS_LEN) { 242 return BLANKS; 243 } 244 245 return BLANKS.substring(0, indent + 1); 246 } 247 248 } 249 } 250