1 /* 2 * Copyright (c) 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package stream.XMLStreamWriterTest; 27 28 import java.io.ByteArrayInputStream; 29 import java.io.ByteArrayOutputStream; 30 import java.io.InputStream; 31 import java.io.OutputStreamWriter; 32 33 import javax.xml.stream.XMLInputFactory; 34 import javax.xml.stream.XMLOutputFactory; 35 import javax.xml.stream.XMLStreamConstants; 36 import javax.xml.stream.XMLStreamException; 37 import javax.xml.stream.XMLStreamReader; 38 import javax.xml.stream.XMLStreamWriter; 39 40 import org.testng.Assert; 41 import org.testng.annotations.Test; 42 import org.testng.annotations.DataProvider; 43 44 /* 45 * @test 46 * @bug 8145974 47 * @modules javax.xml 48 * @summary Check that XMLStreamWriter generates valid xml with surrogate pair 49 * used within element text 50 */ 51 52 public class SurrogatesTest { 53 54 // Test that valid surrogate characters can be written/readen by xml stream 55 // reader/writer 56 @Test(dataProvider = "validData") 57 public void xmlWithValidSurrogatesTest(String content) 58 throws Exception { 59 generateAndReadXml(content); 60 } 61 62 // Test that unbalanced surrogate character will 63 @Test(dataProvider = "invalidData", 64 expectedExceptions = XMLStreamException.class) 65 public void xmlWithUnbalancedSurrogatesTest(String content) 66 throws Exception { 67 generateAndReadXml(content); 68 } 69 70 // Generates xml content with XMLStreamWriter and read it to check 71 // for correctness of xml and generated data 72 void generateAndReadXml(String content) throws Exception { 73 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 74 XMLOutputFactory factory = XMLOutputFactory.newInstance(); 75 OutputStreamWriter streamWriter = new OutputStreamWriter(stream); 76 XMLStreamWriter writer = factory.createXMLStreamWriter(streamWriter); 77 78 // Generate xml with selected stream writer type 79 generateXML(writer, content); 80 String output = stream.toString(); 81 System.out.println("Generated xml: " + output); 82 // Read generated xml with StAX parser 83 readXML(output.getBytes(), content); 84 } 85 86 // Generates XML with provided xml stream writer. Provided string 87 // is inserted into xml twice: with usage of writeCharacters( String ) 88 // and writeCharacters( char [], int , int ) 89 private void generateXML(XMLStreamWriter writer, String sequence) 90 throws XMLStreamException { 91 char[] seqArr = sequence.toCharArray(); 92 writer.writeStartDocument(); 93 writer.writeStartElement("root"); 94 95 // Use writeCharacters( String ) to write characters 96 writer.writeStartElement("writeCharactersWithString"); 97 writer.writeCharacters(sequence); 98 writer.writeEndElement(); 99 100 // Use writeCharacters( char [], int , int ) to write characters 101 writer.writeStartElement("writeCharactersWithArray"); 102 writer.writeCharacters(seqArr, 0, seqArr.length); 103 writer.writeEndElement(); 104 105 // Close root element and document 106 writer.writeEndElement(); 107 writer.writeEndDocument(); 108 writer.flush(); 109 writer.close(); 110 } 111 112 // Reads generated XML data and check if it contains expected 113 // text in writeCharactersWithString and writeCharactersWithArray 114 // elements 115 private void readXML(byte[] xmlData, String expectedContent) 116 throws Exception { 117 InputStream stream = new ByteArrayInputStream(xmlData); 118 XMLInputFactory factory = XMLInputFactory.newInstance(); 119 XMLStreamReader xmlReader 120 = factory.createXMLStreamReader(stream); 121 boolean inTestElement = false; 122 StringBuilder sb = new StringBuilder(); 123 while (xmlReader.hasNext()) { 124 String ename; 125 switch (xmlReader.getEventType()) { 126 case XMLStreamConstants.START_ELEMENT: 127 ename = xmlReader.getLocalName(); 128 if (ename.equals("writeCharactersWithString") 129 || ename.equals("writeCharactersWithArray")) { 130 inTestElement = true; 131 } 132 break; 133 case XMLStreamConstants.END_ELEMENT: 134 ename = xmlReader.getLocalName(); 135 if (ename.equals("writeCharactersWithString") 136 || ename.equals("writeCharactersWithArray")) { 137 inTestElement = false; 138 String content = sb.toString(); 139 System.out.println(ename + " text:'" + content + "' expected:'" + expectedContent+"'"); 140 Assert.assertEquals(content, expectedContent); 141 sb.setLength(0); 142 } 143 break; 144 case XMLStreamConstants.CHARACTERS: 145 if (inTestElement) { 146 sb.append(xmlReader.getText()); 147 } 148 break; 149 } 150 xmlReader.next(); 151 } 152 } 153 154 @DataProvider(name = "validData") 155 Object[][] getValidData() { 156 return new Object[][] { 157 {"Don't Worry Be \uD83D\uDE0A"}, 158 {"BMP characters \uE000\uFFFD"}, 159 {"Simple text"}, 160 }; 161 } 162 163 @DataProvider(name = "invalidData") 164 Object[][] getInvalidData() { 165 return new Object[][] { 166 {"Unbalanced surrogate \uD83D"}, 167 {"Unbalanced surrogate \uD83Dis here"}, 168 {"Surrogate with followup BMP\uD83D\uFFF9"}, 169 }; 170 } 171 }