1/* 2 * Copyright (c) 2017, 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 24/* 25 * @test 26 * @bug 8159058 27 * @summary Test that empty default namespace declaration clears the 28 * default namespace value 29 * @modules java.xml.ws/com.sun.xml.internal.ws.api 30 * java.xml.ws/com.sun.xml.internal.ws.api.message.saaj 31 * java.xml.ws/com.sun.xml.internal.ws.message.stream 32 * @run testng/othervm SaajEmptyNamespaceTest 33 */ 34 35import com.sun.xml.internal.ws.api.SOAPVersion; 36import com.sun.xml.internal.ws.api.message.saaj.SAAJFactory; 37import com.sun.xml.internal.ws.message.stream.StreamMessage; 38import java.io.ByteArrayInputStream; 39import java.io.StringReader; 40import java.io.StringWriter; 41import java.io.UnsupportedEncodingException; 42import javax.xml.namespace.QName; 43import javax.xml.soap.MessageFactory; 44import javax.xml.soap.SOAPBody; 45import javax.xml.soap.SOAPElement; 46import javax.xml.soap.SOAPException; 47import javax.xml.soap.SOAPMessage; 48import javax.xml.stream.XMLInputFactory; 49import javax.xml.stream.XMLStreamReader; 50import javax.xml.transform.OutputKeys; 51import javax.xml.transform.Transformer; 52import javax.xml.transform.TransformerException; 53import javax.xml.transform.TransformerFactory; 54import javax.xml.transform.dom.DOMSource; 55import javax.xml.transform.stream.StreamResult; 56import javax.xml.transform.stream.StreamSource; 57import org.testng.Assert; 58import org.testng.annotations.Test; 59import org.w3c.dom.Node; 60 61public class SaajEmptyNamespaceTest { 62 63 /* 64 * Test that SOAP message with default namespace declaration that contains empty 65 * string is properly processed by SAAJ reader. 66 */ 67 @Test 68 public void testResetDefaultNamespaceSAAJ() throws Exception { 69 // Create SOAP message from XML string and process it with SAAJ reader 70 XMLStreamReader envelope = XMLInputFactory.newFactory().createXMLStreamReader( 71 new StringReader(INPUT_SOAP_MESSAGE)); 72 StreamMessage streamMessage = new StreamMessage(SOAPVersion.SOAP_11, 73 envelope, null); 74 SAAJFactory saajFact = new SAAJFactory(); 75 SOAPMessage soapMessage = saajFact.readAsSOAPMessage(SOAPVersion.SOAP_11, streamMessage); 76 77 // Check if constructed object model meets local names and namespace expectations 78 SOAPElement request = (SOAPElement) soapMessage.getSOAPBody().getFirstChild(); 79 // Check top body element name 80 Assert.assertEquals(request.getLocalName(), "SampleServiceRequest"); 81 // Check top body element namespace 82 Assert.assertEquals(request.getNamespaceURI(), TEST_NS); 83 SOAPElement params = (SOAPElement) request.getFirstChild(); 84 // Check first child name 85 Assert.assertEquals(params.getLocalName(), "RequestParams"); 86 // Check if first child namespace is null 87 Assert.assertNull(params.getNamespaceURI()); 88 89 // Check inner elements of the first child 90 SOAPElement param1 = (SOAPElement) params.getFirstChild(); 91 Assert.assertEquals(param1.getLocalName(), "Param1"); 92 Assert.assertNull(param1.getNamespaceURI()); 93 SOAPElement param2 = (SOAPElement) params.getChildNodes().item(1); 94 Assert.assertEquals(param2.getLocalName(), "Param2"); 95 Assert.assertNull(param2.getNamespaceURI()); 96 // Check full content of SOAP body 97 Assert.assertEquals(nodeToText(request), EXPECTED_RESULT); 98 } 99 100 /* 101 * Test that adding element with explicitly null namespace URI shall put the 102 * element into global namespace. Namespace declarations are not added explicitly. 103 */ 104 @Test 105 public void testAddElementToNullNsNoDeclarations() throws Exception { 106 // Create empty SOAP message 107 SOAPMessage msg = createSoapMessage(); 108 SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); 109 110 // Add elements 111 SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); 112 SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", null); 113 SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); 114 115 // Check namespace URIs 116 Assert.assertNull(childGlobalNS.getNamespaceURI()); 117 Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); 118 } 119 120 /* 121 * Test that adding element with explicitly empty namespace URI shall put 122 * the element into global namespace. Namespace declarations are not added 123 * explicitly. 124 */ 125 @Test 126 public void testAddElementToGlobalNsNoDeclarations() throws Exception { 127 // Create empty SOAP message 128 SOAPMessage msg = createSoapMessage(); 129 SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); 130 131 // Add elements 132 SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); 133 SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", ""); 134 SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); 135 136 // Check namespace URIs 137 Assert.assertNull(childGlobalNS.getNamespaceURI()); 138 Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); 139 } 140 141 /* 142 * Test that adding element with explicitly empty namespace URI set via QName 143 * shall put the element into global namespace. 144 */ 145 @Test 146 public void testAddElementToNullNsQName() throws Exception { 147 // Create empty SOAP message 148 SOAPMessage msg = createSoapMessage(); 149 SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); 150 151 // Add elements 152 SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); 153 parentExplicitNS.addNamespaceDeclaration("", TEST_NS); 154 SOAPElement childGlobalNS = parentExplicitNS.addChildElement(new QName(null, "global-child")); 155 childGlobalNS.addNamespaceDeclaration("", ""); 156 SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); 157 SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); 158 159 // Check namespace URIs 160 Assert.assertNull(childGlobalNS.getNamespaceURI()); 161 Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); 162 Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); 163 } 164 165 /* 166 * Test that adding element with explicitly empty namespace URI shall put 167 * the element into global namespace. 168 */ 169 @Test 170 public void testAddElementToGlobalNs() throws Exception { 171 // Create empty SOAP message 172 SOAPMessage msg = createSoapMessage(); 173 SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); 174 175 // Add elements 176 SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); 177 parentExplicitNS.addNamespaceDeclaration("", TEST_NS); 178 SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", ""); 179 childGlobalNS.addNamespaceDeclaration("", ""); 180 SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); 181 SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); 182 183 // Check namespace URIs 184 Assert.assertNull(childGlobalNS.getNamespaceURI()); 185 Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); 186 Assert.assertEquals(childDefaultNS.getNamespaceURI(), TEST_NS); 187 } 188 189 /* 190 * Test that adding element with explicitly null namespace URI shall put 191 * the element into global namespace. 192 */ 193 @Test 194 public void testAddElementToNullNs() throws Exception { 195 // Create empty SOAP message 196 SOAPMessage msg = createSoapMessage(); 197 SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); 198 199 // Add elements 200 SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); 201 parentExplicitNS.addNamespaceDeclaration("", TEST_NS); 202 SOAPElement childGlobalNS = parentExplicitNS.addChildElement("global-child", "", null); 203 childGlobalNS.addNamespaceDeclaration("", null); 204 SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); 205 SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); 206 207 // Check namespace URIs 208 Assert.assertNull(childGlobalNS.getNamespaceURI()); 209 Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); 210 Assert.assertEquals(TEST_NS, childDefaultNS.getNamespaceURI()); 211 } 212 213 /* 214 * Test that adding element with explicitly empty namespace URI via QName 215 * shall put the element in global namespace. 216 */ 217 @Test 218 public void testAddElementToGlobalNsQName() throws Exception { 219 // Create empty SOAP message 220 SOAPMessage msg = createSoapMessage(); 221 SOAPBody body = msg.getSOAPPart().getEnvelope().getBody(); 222 223 // Add elements 224 SOAPElement parentExplicitNS = body.addChildElement("content", "", TEST_NS); 225 parentExplicitNS.addNamespaceDeclaration("", TEST_NS); 226 SOAPElement childGlobalNS = parentExplicitNS.addChildElement(new QName("", "global-child")); 227 childGlobalNS.addNamespaceDeclaration("", ""); 228 SOAPElement grandChildGlobalNS = childGlobalNS.addChildElement("global-grand-child"); 229 SOAPElement childDefaultNS = parentExplicitNS.addChildElement("default-child"); 230 231 // Check namespace URIs 232 Assert.assertNull(childGlobalNS.getNamespaceURI()); 233 Assert.assertNull(grandChildGlobalNS.getNamespaceURI()); 234 Assert.assertEquals(childDefaultNS.getNamespaceURI(),TEST_NS); 235 } 236 237 // Convert DOM node to text representation 238 private String nodeToText(Node node) throws TransformerException { 239 Transformer trans = TransformerFactory.newInstance().newTransformer(); 240 trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); 241 StringWriter writer = new StringWriter(); 242 StreamResult result = new StreamResult(writer); 243 trans.transform(new DOMSource(node), result); 244 String bodyContent = writer.toString(); 245 System.out.println("SOAP body content read by SAAJ:"+bodyContent); 246 return bodyContent; 247 } 248 249 // Create SOAP message with empty body 250 private static SOAPMessage createSoapMessage() throws SOAPException, UnsupportedEncodingException { 251 String xml = "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" 252 +"<SOAP-ENV:Body/></SOAP-ENV:Envelope>"; 253 MessageFactory mFactory = MessageFactory.newInstance(); 254 SOAPMessage msg = mFactory.createMessage(); 255 msg.getSOAPPart().setContent(new StreamSource(new ByteArrayInputStream(xml.getBytes("utf-8")))); 256 return msg; 257 } 258 259 // Namespace value used in tests 260 private static String TEST_NS = "http://example.org/test"; 261 262 // Content of SOAP message passed to SAAJ factory 263 private static String INPUT_SOAP_MESSAGE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" 264 + "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">" 265 + "<s:Body>" 266 + "<SampleServiceRequest xmlns=\"http://example.org/test\"" 267 + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" 268 + "<RequestParams xmlns=\"\">" 269 + "<Param1>hogehoge</Param1>" 270 + "<Param2>fugafuga</Param2>" 271 + "</RequestParams>" 272 + "</SampleServiceRequest>" 273 + "</s:Body>" 274 + "</s:Envelope>"; 275 276 // Expected body content after SAAJ processing 277 private static String EXPECTED_RESULT = "<SampleServiceRequest" 278 +" xmlns=\"http://example.org/test\">" 279 + "<RequestParams xmlns=\"\">" 280 + "<Param1>hogehoge</Param1>" 281 + "<Param2>fugafuga</Param2>" 282 + "</RequestParams>" 283 + "</SampleServiceRequest>"; 284} 285