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