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