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