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