src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java

Thu, 12 Jan 2017 00:25:07 +0300

author
aefimov
date
Thu, 12 Jan 2017 00:25:07 +0300
changeset 1460
c946a5cc042f
parent 1341
e5cc521294d8
child 1550
c4309a2d981b
permissions
-rw-r--r--

8159058: SAXParseException when sending soap message
Reviewed-by: lancea, coffeys

aoqi@0 1 /*
aefimov@1341 2 * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.ws.api.message.saaj;
aoqi@0 27
aefimov@1341 28 import java.util.Iterator;
aoqi@0 29 import java.util.Arrays;
aefimov@1341 30 import java.util.List;
aefimov@1341 31 import java.util.LinkedList;
aoqi@0 32
aoqi@0 33 import javax.xml.namespace.NamespaceContext;
aoqi@0 34 import javax.xml.namespace.QName;
aoqi@0 35 import javax.xml.soap.SOAPElement;
aoqi@0 36 import javax.xml.soap.SOAPException;
aoqi@0 37 import javax.xml.soap.SOAPMessage;
aoqi@0 38 import javax.xml.stream.XMLStreamException;
aoqi@0 39 import javax.xml.stream.XMLStreamWriter;
aoqi@0 40
aoqi@0 41 import org.w3c.dom.Comment;
aoqi@0 42 import org.w3c.dom.Node;
aoqi@0 43
aoqi@0 44 /**
aoqi@0 45 * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface.
aoqi@0 46 *
aefimov@1341 47 * <p>
aefimov@1341 48 * Defers creation of SOAPElement until all the aspects of the name of the element are known.
aefimov@1341 49 * In some cases, the namespace uri is indicated only by the {@link #writeNamespace(String, String)} call.
aefimov@1341 50 * After opening an element ({@code writeStartElement}, {@code writeEmptyElement} methods), all attributes
aefimov@1341 51 * and namespace assignments are retained within {@link DeferredElement} object ({@code deferredElement} field).
aefimov@1341 52 * As soon as any other method than {@code writeAttribute}, {@code writeNamespace}, {@code writeDefaultNamespace}
aefimov@1341 53 * or {@code setNamespace} is called, the contents of {@code deferredElement} is transformed into new SOAPElement
aefimov@1341 54 * (which is appropriately inserted into the SOAPMessage under construction).
aefimov@1341 55 * This mechanism is necessary to fix JDK-8159058 issue.
aefimov@1341 56 * </p>
aefimov@1341 57 *
aoqi@0 58 * @author shih-chang.chen@oracle.com
aoqi@0 59 */
aoqi@0 60 public class SaajStaxWriter implements XMLStreamWriter {
aoqi@0 61
aoqi@0 62 protected SOAPMessage soap;
aoqi@0 63 protected String envURI;
aoqi@0 64 protected SOAPElement currentElement;
aefimov@1341 65 protected DeferredElement deferredElement;
aoqi@0 66
aoqi@0 67 static final protected String Envelope = "Envelope";
aoqi@0 68 static final protected String Header = "Header";
aoqi@0 69 static final protected String Body = "Body";
aoqi@0 70 static final protected String xmlns = "xmlns";
aoqi@0 71
aoqi@0 72 public SaajStaxWriter(final SOAPMessage msg) throws SOAPException {
aoqi@0 73 soap = msg;
aoqi@0 74 currentElement = soap.getSOAPPart().getEnvelope();
aoqi@0 75 envURI = currentElement.getNamespaceURI();
aefimov@1341 76 this.deferredElement = new DeferredElement();
aoqi@0 77 }
aoqi@0 78
aoqi@0 79 public SOAPMessage getSOAPMessage() {
aoqi@0 80 return soap;
aoqi@0 81 }
aoqi@0 82
aoqi@0 83 @Override
aoqi@0 84 public void writeStartElement(final String localName) throws XMLStreamException {
aefimov@1341 85 currentElement = deferredElement.flushTo(currentElement);
aefimov@1341 86 deferredElement.setLocalName(localName);
aoqi@0 87 }
aoqi@0 88
aoqi@0 89 @Override
aoqi@0 90 public void writeStartElement(final String ns, final String ln) throws XMLStreamException {
aoqi@0 91 writeStartElement(null, ln, ns);
aoqi@0 92 }
aoqi@0 93
aoqi@0 94 @Override
aoqi@0 95 public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException {
aefimov@1341 96 currentElement = deferredElement.flushTo(currentElement);
aefimov@1341 97
aefimov@1341 98 if (envURI.equals(ns)) {
aefimov@1341 99 try {
aoqi@0 100 if (Envelope.equals(ln)) {
aoqi@0 101 currentElement = soap.getSOAPPart().getEnvelope();
aoqi@0 102 fixPrefix(prefix);
aoqi@0 103 return;
aoqi@0 104 } else if (Header.equals(ln)) {
aoqi@0 105 currentElement = soap.getSOAPHeader();
aoqi@0 106 fixPrefix(prefix);
aoqi@0 107 return;
aoqi@0 108 } else if (Body.equals(ln)) {
aoqi@0 109 currentElement = soap.getSOAPBody();
aoqi@0 110 fixPrefix(prefix);
aoqi@0 111 return;
aoqi@0 112 }
aefimov@1341 113 } catch (SOAPException e) {
aefimov@1341 114 throw new XMLStreamException(e);
aoqi@0 115 }
aefimov@1341 116
aoqi@0 117 }
aefimov@1341 118
aefimov@1341 119 deferredElement.setLocalName(ln);
aefimov@1341 120 deferredElement.setNamespaceUri(ns);
aefimov@1341 121 deferredElement.setPrefix(prefix);
aefimov@1341 122
aoqi@0 123 }
aoqi@0 124
aoqi@0 125 private void fixPrefix(final String prfx) throws XMLStreamException {
aoqi@0 126 String oldPrfx = currentElement.getPrefix();
aoqi@0 127 if (prfx != null && !prfx.equals(oldPrfx)) {
aoqi@0 128 currentElement.setPrefix(prfx);
aoqi@0 129 }
aoqi@0 130 }
aoqi@0 131
aoqi@0 132 @Override
aoqi@0 133 public void writeEmptyElement(final String uri, final String ln) throws XMLStreamException {
aoqi@0 134 writeStartElement(null, ln, uri);
aoqi@0 135 }
aoqi@0 136
aoqi@0 137 @Override
aoqi@0 138 public void writeEmptyElement(final String prefix, final String ln, final String uri) throws XMLStreamException {
aoqi@0 139 writeStartElement(prefix, ln, uri);
aoqi@0 140 }
aoqi@0 141
aoqi@0 142 @Override
aoqi@0 143 public void writeEmptyElement(final String ln) throws XMLStreamException {
aoqi@0 144 writeStartElement(null, ln, null);
aoqi@0 145 }
aoqi@0 146
aoqi@0 147 @Override
aoqi@0 148 public void writeEndElement() throws XMLStreamException {
aefimov@1341 149 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 150 if (currentElement != null) currentElement = currentElement.getParentElement();
aoqi@0 151 }
aoqi@0 152
aoqi@0 153 @Override
aoqi@0 154 public void writeEndDocument() throws XMLStreamException {
aefimov@1341 155 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 156 }
aoqi@0 157
aoqi@0 158 @Override
aoqi@0 159 public void close() throws XMLStreamException {
aoqi@0 160 }
aoqi@0 161
aoqi@0 162 @Override
aoqi@0 163 public void flush() throws XMLStreamException {
aoqi@0 164 }
aoqi@0 165
aoqi@0 166 @Override
aoqi@0 167 public void writeAttribute(final String ln, final String val) throws XMLStreamException {
aoqi@0 168 writeAttribute(null, null, ln, val);
aoqi@0 169 }
aoqi@0 170
aoqi@0 171 @Override
aoqi@0 172 public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException {
aefimov@1341 173 if (ns == null && prefix == null && xmlns.equals(ln)) {
aefimov@1341 174 writeNamespace("", value);
aefimov@1341 175 } else {
aefimov@1341 176 if (deferredElement.isInitialized()) {
aefimov@1341 177 deferredElement.addAttribute(prefix, ns, ln, value);
aoqi@0 178 } else {
aefimov@1341 179 addAttibuteToElement(currentElement, prefix, ns, ln, value);
aoqi@0 180 }
aoqi@0 181 }
aoqi@0 182 }
aoqi@0 183
aoqi@0 184 @Override
aoqi@0 185 public void writeAttribute(final String ns, final String ln, final String val) throws XMLStreamException {
aoqi@0 186 writeAttribute(null, ns, ln, val);
aoqi@0 187 }
aoqi@0 188
aoqi@0 189 @Override
aoqi@0 190 public void writeNamespace(String prefix, final String uri) throws XMLStreamException {
aoqi@0 191 // make prefix default if null or "xmlns" (according to javadoc)
aefimov@1341 192 String thePrefix = prefix == null || "xmlns".equals(prefix) ? "" : prefix;
aefimov@1341 193 if (deferredElement.isInitialized()) {
aefimov@1341 194 deferredElement.addNamespaceDeclaration(thePrefix, uri);
aefimov@1341 195 } else {
aefimov@1341 196 try {
aefimov@1341 197 currentElement.addNamespaceDeclaration(thePrefix, uri);
aefimov@1341 198 } catch (SOAPException e) {
aefimov@1341 199 throw new XMLStreamException(e);
aefimov@1341 200 }
aoqi@0 201 }
aoqi@0 202 }
aoqi@0 203
aoqi@0 204 @Override
aoqi@0 205 public void writeDefaultNamespace(final String uri) throws XMLStreamException {
aoqi@0 206 writeNamespace("", uri);
aoqi@0 207 }
aoqi@0 208
aoqi@0 209 @Override
aoqi@0 210 public void writeComment(final String data) throws XMLStreamException {
aefimov@1341 211 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 212 Comment c = soap.getSOAPPart().createComment(data);
aoqi@0 213 currentElement.appendChild(c);
aoqi@0 214 }
aoqi@0 215
aoqi@0 216 @Override
aoqi@0 217 public void writeProcessingInstruction(final String target) throws XMLStreamException {
aefimov@1341 218 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 219 Node n = soap.getSOAPPart().createProcessingInstruction(target, "");
aoqi@0 220 currentElement.appendChild(n);
aoqi@0 221 }
aoqi@0 222
aoqi@0 223 @Override
aoqi@0 224 public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
aefimov@1341 225 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 226 Node n = soap.getSOAPPart().createProcessingInstruction(target, data);
aoqi@0 227 currentElement.appendChild(n);
aoqi@0 228 }
aoqi@0 229
aoqi@0 230 @Override
aoqi@0 231 public void writeCData(final String data) throws XMLStreamException {
aefimov@1341 232 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 233 Node n = soap.getSOAPPart().createCDATASection(data);
aoqi@0 234 currentElement.appendChild(n);
aoqi@0 235 }
aoqi@0 236
aoqi@0 237 @Override
aoqi@0 238 public void writeDTD(final String dtd) throws XMLStreamException {
aefimov@1341 239 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 240 }
aoqi@0 241
aoqi@0 242 @Override
aoqi@0 243 public void writeEntityRef(final String name) throws XMLStreamException {
aefimov@1341 244 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 245 Node n = soap.getSOAPPart().createEntityReference(name);
aoqi@0 246 currentElement.appendChild(n);
aoqi@0 247 }
aoqi@0 248
aoqi@0 249 @Override
aoqi@0 250 public void writeStartDocument() throws XMLStreamException {
aoqi@0 251 }
aoqi@0 252
aoqi@0 253 @Override
aoqi@0 254 public void writeStartDocument(final String version) throws XMLStreamException {
aoqi@0 255 if (version != null) soap.getSOAPPart().setXmlVersion(version);
aoqi@0 256 }
aoqi@0 257
aoqi@0 258 @Override
aoqi@0 259 public void writeStartDocument(final String encoding, final String version) throws XMLStreamException {
aoqi@0 260 if (version != null) soap.getSOAPPart().setXmlVersion(version);
aoqi@0 261 if (encoding != null) {
aoqi@0 262 try {
aoqi@0 263 soap.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, encoding);
aoqi@0 264 } catch (SOAPException e) {
aoqi@0 265 throw new XMLStreamException(e);
aoqi@0 266 }
aoqi@0 267 }
aoqi@0 268 }
aoqi@0 269
aoqi@0 270 @Override
aoqi@0 271 public void writeCharacters(final String text) throws XMLStreamException {
aefimov@1341 272 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 273 try {
aoqi@0 274 currentElement.addTextNode(text);
aoqi@0 275 } catch (SOAPException e) {
aoqi@0 276 throw new XMLStreamException(e);
aoqi@0 277 }
aoqi@0 278 }
aoqi@0 279
aoqi@0 280 @Override
aoqi@0 281 public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
aefimov@1341 282 currentElement = deferredElement.flushTo(currentElement);
aoqi@0 283 char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len);
aoqi@0 284 try {
aoqi@0 285 currentElement.addTextNode(new String(chr));
aoqi@0 286 } catch (SOAPException e) {
aoqi@0 287 throw new XMLStreamException(e);
aoqi@0 288 }
aoqi@0 289 }
aoqi@0 290
aoqi@0 291 @Override
aoqi@0 292 public String getPrefix(final String uri) throws XMLStreamException {
aoqi@0 293 return currentElement.lookupPrefix(uri);
aoqi@0 294 }
aoqi@0 295
aoqi@0 296 @Override
aoqi@0 297 public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
aefimov@1341 298 // TODO: this in fact is not what would be expected from XMLStreamWriter
aefimov@1341 299 // (e.g. XMLStreamWriter for writing to output stream does not write anything as result of
aefimov@1341 300 // this method, it just rememebers that given prefix is associated with the given uri
aefimov@1341 301 // for the scope; to actually declare the prefix assignment in the resulting XML, one
aefimov@1341 302 // needs to call writeNamespace(...) method
aefimov@1341 303 // Kept for backwards compatibility reasons - this might be worth of further investigation.
aefimov@1341 304 if (deferredElement.isInitialized()) {
aefimov@1341 305 deferredElement.addNamespaceDeclaration(prefix, uri);
aefimov@1341 306 } else {
aefimov@1341 307 throw new XMLStreamException("Namespace not associated with any element");
aoqi@0 308 }
aoqi@0 309 }
aoqi@0 310
aoqi@0 311 @Override
aoqi@0 312 public void setDefaultNamespace(final String uri) throws XMLStreamException {
aoqi@0 313 setPrefix("", uri);
aoqi@0 314 }
aoqi@0 315
aoqi@0 316 @Override
aoqi@0 317 public void setNamespaceContext(final NamespaceContext context)throws XMLStreamException {
aoqi@0 318 throw new UnsupportedOperationException();
aoqi@0 319 }
aoqi@0 320
aoqi@0 321 @Override
aoqi@0 322 public Object getProperty(final String name) throws IllegalArgumentException {
aoqi@0 323 //TODO the following line is to make eclipselink happy ... they are aware of this problem -
aoqi@0 324 if (javax.xml.stream.XMLOutputFactory.IS_REPAIRING_NAMESPACES.equals(name)) return Boolean.FALSE;
aoqi@0 325 return null;
aoqi@0 326 }
aoqi@0 327
aoqi@0 328 @Override
aoqi@0 329 public NamespaceContext getNamespaceContext() {
aoqi@0 330 return new NamespaceContext() {
aoqi@0 331 public String getNamespaceURI(final String prefix) {
aoqi@0 332 return currentElement.getNamespaceURI(prefix);
aoqi@0 333 }
aoqi@0 334 public String getPrefix(final String namespaceURI) {
aoqi@0 335 return currentElement.lookupPrefix(namespaceURI);
aoqi@0 336 }
aoqi@0 337 public Iterator getPrefixes(final String namespaceURI) {
aefimov@1341 338 return new Iterator<String>() {
aoqi@0 339 String prefix = getPrefix(namespaceURI);
aoqi@0 340 public boolean hasNext() {
aoqi@0 341 return (prefix != null);
aoqi@0 342 }
aefimov@1341 343 public String next() {
aoqi@0 344 if (!hasNext()) throw new java.util.NoSuchElementException();
aoqi@0 345 String next = prefix;
aoqi@0 346 prefix = null;
aoqi@0 347 return next;
aoqi@0 348 }
aoqi@0 349 public void remove() {}
aoqi@0 350 };
aoqi@0 351 }
aoqi@0 352 };
aoqi@0 353 }
aefimov@1341 354
aefimov@1341 355 static void addAttibuteToElement(SOAPElement element, String prefix, String ns, String ln, String value)
aefimov@1341 356 throws XMLStreamException {
aefimov@1341 357 try {
aefimov@1341 358 if (ns == null) {
aefimov@1341 359 element.setAttributeNS("", ln, value);
aefimov@1341 360 } else {
aefimov@1341 361 QName name = prefix == null ? new QName(ns, ln) : new QName(ns, ln, prefix);
aefimov@1341 362 element.addAttribute(name, value);
aefimov@1341 363 }
aefimov@1341 364 } catch (SOAPException e) {
aefimov@1341 365 throw new XMLStreamException(e);
aefimov@1341 366 }
aefimov@1341 367 }
aefimov@1341 368
aefimov@1341 369 /**
aefimov@1341 370 * Holds details of element that needs to be deferred in order to manage namespace assignments correctly.
aefimov@1341 371 *
aefimov@1341 372 * <p>
aefimov@1341 373 * An instance of can be set with all the aspects of the element name (local name, prefix, namespace uri).
aefimov@1341 374 * Attributes and namespace declarations (special case of attribute) can be added.
aefimov@1341 375 * Namespace declarations are handled so that the element namespace is updated if it is implied by the namespace
aefimov@1341 376 * declaration and the namespace was not set to non-{@code null} value previously.
aefimov@1341 377 * </p>
aefimov@1341 378 *
aefimov@1341 379 * <p>
aefimov@1341 380 * The state of this object can be {@link #flushTo(SOAPElement) flushed} to SOAPElement - new SOAPElement will
aefimov@1341 381 * be added a child element; the new element will have exactly the shape as represented by the state of this
aefimov@1341 382 * object. Note that the {@link #flushTo(SOAPElement)} method does nothing
aefimov@1341 383 * (and returns the argument immediately) if the state of this object is not initialized
aefimov@1341 384 * (i.e. local name is null).
aefimov@1341 385 * </p>
aefimov@1341 386 *
aefimov@1341 387 * @author ondrej.cerny@oracle.com
aefimov@1341 388 */
aefimov@1341 389 static class DeferredElement {
aefimov@1341 390 private String prefix;
aefimov@1341 391 private String localName;
aefimov@1341 392 private String namespaceUri;
aefimov@1341 393 private final List<NamespaceDeclaration> namespaceDeclarations;
aefimov@1341 394 private final List<AttributeDeclaration> attributeDeclarations;
aefimov@1341 395
aefimov@1341 396 DeferredElement() {
aefimov@1341 397 this.namespaceDeclarations = new LinkedList<NamespaceDeclaration>();
aefimov@1341 398 this.attributeDeclarations = new LinkedList<AttributeDeclaration>();
aefimov@1341 399 reset();
aefimov@1341 400 }
aefimov@1341 401
aefimov@1341 402
aefimov@1341 403 /**
aefimov@1341 404 * Set prefix of the element.
aefimov@1341 405 * @param prefix namespace prefix
aefimov@1341 406 */
aefimov@1341 407 public void setPrefix(final String prefix) {
aefimov@1341 408 this.prefix = prefix;
aefimov@1341 409 }
aefimov@1341 410
aefimov@1341 411 /**
aefimov@1341 412 * Set local name of the element.
aefimov@1341 413 *
aefimov@1341 414 * <p>
aefimov@1341 415 * This method initializes the element.
aefimov@1341 416 * </p>
aefimov@1341 417 *
aefimov@1341 418 * @param localName local name {@code not null}
aefimov@1341 419 */
aefimov@1341 420 public void setLocalName(final String localName) {
aefimov@1341 421 if (localName == null) {
aefimov@1341 422 throw new IllegalArgumentException("localName can not be null");
aefimov@1341 423 }
aefimov@1341 424 this.localName = localName;
aefimov@1341 425 }
aefimov@1341 426
aefimov@1341 427 /**
aefimov@1341 428 * Set namespace uri.
aefimov@1341 429 *
aefimov@1341 430 * @param namespaceUri namespace uri
aefimov@1341 431 */
aefimov@1341 432 public void setNamespaceUri(final String namespaceUri) {
aefimov@1341 433 this.namespaceUri = namespaceUri;
aefimov@1341 434 }
aefimov@1341 435
aefimov@1341 436 /**
aefimov@1341 437 * Adds namespace prefix assignment to the element.
aefimov@1341 438 *
aefimov@1341 439 * @param prefix prefix (not {@code null})
aefimov@1341 440 * @param namespaceUri namespace uri
aefimov@1341 441 */
aefimov@1341 442 public void addNamespaceDeclaration(final String prefix, final String namespaceUri) {
aefimov@1341 443 if (null == this.namespaceUri && null != namespaceUri && prefix.equals(emptyIfNull(this.prefix))) {
aefimov@1341 444 this.namespaceUri = namespaceUri;
aefimov@1341 445 }
aefimov@1341 446 this.namespaceDeclarations.add(new NamespaceDeclaration(prefix, namespaceUri));
aefimov@1341 447 }
aefimov@1341 448
aefimov@1341 449 /**
aefimov@1341 450 * Adds attribute to the element.
aefimov@1341 451 * @param prefix prefix
aefimov@1341 452 * @param ns namespace
aefimov@1341 453 * @param ln local name
aefimov@1341 454 * @param value value
aefimov@1341 455 */
aefimov@1341 456 public void addAttribute(final String prefix, final String ns, final String ln, final String value) {
aefimov@1341 457 if (ns == null && prefix == null && xmlns.equals(ln)) {
aefimov@1341 458 this.addNamespaceDeclaration(prefix, value);
aefimov@1341 459 } else {
aefimov@1341 460 this.attributeDeclarations.add(new AttributeDeclaration(prefix, ns, ln, value));
aefimov@1341 461 }
aefimov@1341 462 }
aefimov@1341 463
aefimov@1341 464 /**
aefimov@1341 465 * Flushes state of this element to the {@code target} element.
aefimov@1341 466 *
aefimov@1341 467 * <p>
aefimov@1341 468 * If this element is initialized then it is added with all the namespace declarations and attributes
aefimov@1341 469 * to the {@code target} element as a child. The state of this element is reset to uninitialized.
aefimov@1341 470 * The newly added element object is returned.
aefimov@1341 471 * </p>
aefimov@1341 472 * <p>
aefimov@1341 473 * If this element is not initialized then the {@code target} is returned immediately, nothing else is done.
aefimov@1341 474 * </p>
aefimov@1341 475 *
aefimov@1341 476 * @param target target element
aefimov@1341 477 * @return {@code target} or new element
aefimov@1341 478 * @throws XMLStreamException on error
aefimov@1341 479 */
aefimov@1341 480 public SOAPElement flushTo(final SOAPElement target) throws XMLStreamException {
aefimov@1341 481 try {
aefimov@1341 482 if (this.localName != null) {
aefimov@1341 483 // add the element appropriately (based on namespace declaration)
aefimov@1341 484 final SOAPElement newElement;
aefimov@1341 485 if (this.namespaceUri == null) {
aefimov@1341 486 // add element with inherited scope
aefimov@1341 487 newElement = target.addChildElement(this.localName);
aefimov@1341 488 } else if (prefix == null) {
aefimov@1341 489 newElement = target.addChildElement(new QName(this.namespaceUri, this.localName));
aefimov@1341 490 } else {
aefimov@1341 491 newElement = target.addChildElement(this.localName, this.prefix, this.namespaceUri);
aefimov@1341 492 }
aefimov@1341 493 // add namespace declarations
aefimov@1341 494 for (NamespaceDeclaration namespace : this.namespaceDeclarations) {
aefimov@1341 495 target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri);
aefimov@1341 496 }
aefimov@1341 497 // add attribute declarations
aefimov@1341 498 for (AttributeDeclaration attribute : this.attributeDeclarations) {
aefimov@1341 499 addAttibuteToElement(newElement,
aefimov@1341 500 attribute.prefix, attribute.namespaceUri, attribute.localName, attribute.value);
aefimov@1341 501 }
aefimov@1341 502 // reset state
aefimov@1341 503 this.reset();
aefimov@1341 504
aefimov@1341 505 return newElement;
aefimov@1341 506 } else {
aefimov@1341 507 return target;
aefimov@1341 508 }
aefimov@1341 509 // else after reset state -> not initialized
aefimov@1341 510 } catch (SOAPException e) {
aefimov@1341 511 throw new XMLStreamException(e);
aefimov@1341 512 }
aefimov@1341 513 }
aefimov@1341 514
aefimov@1341 515 /**
aefimov@1341 516 * Is the element initialized?
aefimov@1341 517 * @return boolean indicating whether it was initialized after last flush
aefimov@1341 518 */
aefimov@1341 519 public boolean isInitialized() {
aefimov@1341 520 return this.localName != null;
aefimov@1341 521 }
aefimov@1341 522
aefimov@1341 523 private void reset() {
aefimov@1341 524 this.localName = null;
aefimov@1341 525 this.prefix = null;
aefimov@1341 526 this.namespaceUri = null;
aefimov@1341 527 this.namespaceDeclarations.clear();
aefimov@1341 528 this.attributeDeclarations.clear();
aefimov@1341 529 }
aefimov@1341 530
aefimov@1341 531 private static String emptyIfNull(String s) {
aefimov@1341 532 return s == null ? "" : s;
aefimov@1341 533 }
aefimov@1341 534 }
aefimov@1341 535
aefimov@1341 536 static class NamespaceDeclaration {
aefimov@1341 537 final String prefix;
aefimov@1341 538 final String namespaceUri;
aefimov@1341 539
aefimov@1341 540 NamespaceDeclaration(String prefix, String namespaceUri) {
aefimov@1341 541 this.prefix = prefix;
aefimov@1341 542 this.namespaceUri = namespaceUri;
aefimov@1341 543 }
aefimov@1341 544 }
aefimov@1341 545
aefimov@1341 546 static class AttributeDeclaration {
aefimov@1341 547 final String prefix;
aefimov@1341 548 final String namespaceUri;
aefimov@1341 549 final String localName;
aefimov@1341 550 final String value;
aefimov@1341 551
aefimov@1341 552 AttributeDeclaration(String prefix, String namespaceUri, String localName, String value) {
aefimov@1341 553 this.prefix = prefix;
aefimov@1341 554 this.namespaceUri = namespaceUri;
aefimov@1341 555 this.localName = localName;
aefimov@1341 556 this.value = value;
aefimov@1341 557 }
aefimov@1341 558 }
aoqi@0 559 }

mercurial