1 /* 2 * Copyright (c) 2014, 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 com.sun.xml.internal.messaging.saaj.util.stax; 27 28 import java.util.Arrays; 29 import java.util.Iterator; 30 31 import javax.xml.namespace.NamespaceContext; 32 import javax.xml.namespace.QName; 33 import javax.xml.soap.SOAPElement; 34 import javax.xml.soap.SOAPException; 35 import javax.xml.soap.SOAPMessage; 36 import javax.xml.stream.XMLStreamException; 37 import javax.xml.stream.XMLStreamWriter; 38 39 import org.w3c.dom.Comment; 40 import org.w3c.dom.Node; 41 42 /** 43 * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface. 44 * 45 * @author shih-chang.chen@oracle.com 46 */ 47 public class SaajStaxWriter implements XMLStreamWriter { 48 49 protected SOAPMessage soap; 50 protected String envURI; 51 protected SOAPElement currentElement; 52 53 static final protected String Envelope = "Envelope"; 54 static final protected String Header = "Header"; 55 static final protected String Body = "Body"; 56 static final protected String xmlns = "xmlns"; 57 58 private boolean isHeaderSeen = false; 59 60 public SaajStaxWriter(final SOAPMessage msg, String uri) throws SOAPException { 61 soap = msg; 62 this.envURI = uri; 63 } 64 65 public SOAPMessage getSOAPMessage() { 66 return soap; 67 } 68 69 protected SOAPElement getEnvelope() throws SOAPException { 70 return soap.getSOAPPart().getEnvelope(); 71 } 72 73 @Override 74 public void writeStartElement(final String localName) throws XMLStreamException { 75 try { 76 currentElement = currentElement.addChildElement(localName); 77 } catch (SOAPException e) { 78 throw new XMLStreamException(e); 79 } 80 } 81 82 @Override 83 public void writeStartElement(final String ns, final String ln) throws XMLStreamException { 84 writeStartElement(null, ln, ns); 85 } 86 87 @Override 88 public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException { 89 try { 90 if (envURI.equals(ns)) { 91 if (Envelope.equals(ln)) { 92 currentElement = getEnvelope(); 93 fixPrefix(prefix); 94 return; 95 } else if (Header.equals(ln)) { 96 isHeaderSeen = true; 97 currentElement = soap.getSOAPHeader(); 98 fixPrefix(prefix); 99 return; 100 } else if (Body.equals(ln)) { 101 currentElement = soap.getSOAPBody(); 102 fixPrefix(prefix); 103 return; 104 } 105 } 106 currentElement = (prefix == null) ? 107 currentElement.addChildElement(new QName(ns, ln)) : 108 currentElement.addChildElement(ln, prefix, ns); 109 } catch (SOAPException e) { 110 throw new XMLStreamException(e); 111 } 112 } 113 114 private void fixPrefix(final String prfx) throws XMLStreamException { 115 fixPrefix(prfx, currentElement); 116 } 117 118 private void fixPrefix(final String prfx, SOAPElement element) throws XMLStreamException { 119 String oldPrfx = element.getPrefix(); 120 if (prfx != null && !prfx.equals(oldPrfx)) { 121 element.setPrefix(prfx); 122 } 123 } 124 125 @Override 126 public void writeEmptyElement(final String uri, final String ln) throws XMLStreamException { 127 writeStartElement(null, ln, uri); 128 } 129 130 @Override 131 public void writeEmptyElement(final String prefix, final String ln, final String uri) throws XMLStreamException { 132 writeStartElement(prefix, ln, uri); 133 } 134 135 @Override 136 public void writeEmptyElement(final String ln) throws XMLStreamException { 137 writeStartElement(null, ln, null); 138 } 139 140 @Override 141 public void writeEndElement() throws XMLStreamException { 142 if (currentElement != null) currentElement = currentElement.getParentElement(); 143 } 144 145 @Override 146 public void writeEndDocument() throws XMLStreamException { 147 try { 148 if (!isHeaderSeen) { 149 SOAPElement header = soap.getSOAPHeader(); 150 if (header != null) { 151 String prefixAtHeader = header.getPrefix(); 152 SOAPElement env = getEnvelope(); 153 header.detachNode(); 154 if (prefixAtHeader != null && !prefixAtHeader.equals(env.getPrefix())) { 155 env.removeNamespaceDeclaration(prefixAtHeader); 156 } 157 } 158 } 159 } catch (SOAPException e) { 160 throw new XMLStreamException(e); 161 } 162 } 163 164 @Override 165 public void close() throws XMLStreamException { 166 } 167 168 @Override 169 public void flush() throws XMLStreamException { 170 } 171 172 @Override 173 public void writeAttribute(final String ln, final String val) throws XMLStreamException { 174 writeAttribute(null, null, ln, val); 175 } 176 177 @Override 178 public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException { 179 try { 180 if (ns == null) { 181 if (prefix == null && xmlns.equals(ln)) { 182 currentElement.addNamespaceDeclaration("", value); 183 } else { 184 currentElement.setAttributeNS("", ln, value); 185 } 186 } else { 187 QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix); 188 currentElement.addAttribute(name, value); 189 } 190 } catch (SOAPException e) { 191 throw new XMLStreamException(e); 192 } 193 } 194 195 @Override 196 public void writeAttribute(final String ns, final String ln, final String val) throws XMLStreamException { 197 writeAttribute(null, ns, ln, val); 198 } 199 200 @Override 201 public void writeNamespace(String prefix, final String uri) throws XMLStreamException { 202 203 // make prefix default if null or "xmlns" (according to javadoc) 204 if (prefix == null || "xmlns".equals(prefix)) { 205 prefix = ""; 206 } 207 208 try { 209 currentElement.addNamespaceDeclaration(prefix, uri); 210 } catch (SOAPException e) { 211 throw new XMLStreamException(e); 212 } 213 } 214 215 @Override 216 public void writeDefaultNamespace(final String uri) throws XMLStreamException { 217 writeNamespace("", uri); 218 } 219 220 @Override 221 public void writeComment(final String data) throws XMLStreamException { 222 Comment c = soap.getSOAPPart().createComment(data); 223 currentElement.appendChild(c); 224 } 225 226 @Override 227 public void writeProcessingInstruction(final String target) throws XMLStreamException { 228 Node n = soap.getSOAPPart().createProcessingInstruction(target, ""); 229 currentElement.appendChild(n); 230 } 231 232 @Override 233 public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException { 234 Node n = soap.getSOAPPart().createProcessingInstruction(target, data); 235 currentElement.appendChild(n); 236 } 237 238 @Override 239 public void writeCData(final String data) throws XMLStreamException { 240 Node n = soap.getSOAPPart().createCDATASection(data); 241 currentElement.appendChild(n); 242 } 243 244 @Override 245 public void writeDTD(final String dtd) throws XMLStreamException { 246 //TODO ... Don't do anything here 247 } 248 249 @Override 250 public void writeEntityRef(final String name) throws XMLStreamException { 251 Node n = soap.getSOAPPart().createEntityReference(name); 252 currentElement.appendChild(n); 253 } 254 255 @Override 256 public void writeStartDocument() throws XMLStreamException { 257 } 258 259 @Override 260 public void writeStartDocument(final String version) throws XMLStreamException { 261 if (version != null) soap.getSOAPPart().setXmlVersion(version); 262 } 263 264 @Override 265 public void writeStartDocument(final String encoding, final String version) throws XMLStreamException { 266 if (version != null) soap.getSOAPPart().setXmlVersion(version); 267 if (encoding != null) { 268 try { 269 soap.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, encoding); 270 } catch (SOAPException e) { 271 throw new XMLStreamException(e); 272 } 273 } 274 } 275 276 @Override 277 public void writeCharacters(final String text) throws XMLStreamException { 278 try { 279 currentElement.addTextNode(text); 280 } catch (SOAPException e) { 281 throw new XMLStreamException(e); 282 } 283 } 284 285 @Override 286 public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException { 287 char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len); 288 try { 289 currentElement.addTextNode(new String(chr)); 290 } catch (SOAPException e) { 291 throw new XMLStreamException(e); 292 } 293 } 294 295 @Override 296 public String getPrefix(final String uri) throws XMLStreamException { 297 return currentElement.lookupPrefix(uri); 298 } 299 300 @Override 301 public void setPrefix(final String prefix, final String uri) throws XMLStreamException { 302 try { 303 this.currentElement.addNamespaceDeclaration(prefix, uri); 304 } catch (SOAPException e) { 305 throw new XMLStreamException(e); 306 } 307 } 308 309 @Override 310 public void setDefaultNamespace(final String uri) throws XMLStreamException { 311 setPrefix("", uri); 312 } 313 314 @Override 315 public void setNamespaceContext(final NamespaceContext context)throws XMLStreamException { 316 throw new UnsupportedOperationException(); 317 } 318 319 @Override 320 public Object getProperty(final String name) throws IllegalArgumentException { 321 //TODO the following line is to make eclipselink happy ... they are aware of this problem - 322 if (javax.xml.stream.XMLOutputFactory.IS_REPAIRING_NAMESPACES.equals(name)) return Boolean.FALSE; 323 return null; 324 } 325 326 @Override 327 public NamespaceContext getNamespaceContext() { 328 return new NamespaceContext() { 329 public String getNamespaceURI(final String prefix) { 330 return currentElement.getNamespaceURI(prefix); 331 } 332 public String getPrefix(final String namespaceURI) { 333 return currentElement.lookupPrefix(namespaceURI); 334 } 335 public Iterator getPrefixes(final String namespaceURI) { 336 return new Iterator() { 337 String prefix = getPrefix(namespaceURI); 338 public boolean hasNext() { 339 return (prefix != null); 340 } 341 public Object next() { 342 if (!hasNext()) throw new java.util.NoSuchElementException(); 343 String next = prefix; 344 prefix = null; 345 return next; 346 } 347 public void remove() {} 348 }; 349 } 350 }; 351 } 352 }