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