Merge

Tue, 07 Feb 2017 15:33:07 -0800

author
asaha
date
Tue, 07 Feb 2017 15:33:07 -0800
changeset 1462
51d2d96d00c5
parent 1352
62b6998733d3
parent 1461
159698a1ab41
child 1463
4766eaa8490b
child 1466
d03476caf862

Merge

.hgtags file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Mon Feb 06 12:17:19 2017 -0800
     1.2 +++ b/.hgtags	Tue Feb 07 15:33:07 2017 -0800
     1.3 @@ -660,6 +660,8 @@
     1.4  5f84e87f91d5bc36ed026b88d183821e5109d730 jdk8u112-b15
     1.5  d82dd7a24a496e26987caa328d1fb4fc794a4770 jdk8u112-b16
     1.6  021da5d50285a523d4622a727ea1a7019f2b52e4 jdk8u112-b31
     1.7 +4d1398900b3745c3181450e981ed45696a1c97fc jdk8u112-b32
     1.8 +424b6ee9ade3f63228867933fe8a995880379b97 jdk8u112-b33
     1.9  452662a83e5bc6dc7e9425ddd10f6c8fc98d50d8 jdk8u121-b00
    1.10  9cd16be39ca6f2c8f7cc99ad07a77bb9d0696c75 jdk8u121-b01
    1.11  f092b9a890ceeca4a2f4d55cf7d6f3f113cdb462 jdk8u121-b02
    1.12 @@ -674,6 +676,8 @@
    1.13  89aa912be940d6c30f59b80c826f212541912a56 jdk8u121-b11
    1.14  52b3f9fb54ee4304a9c34a2fe07f0c9a49472185 jdk8u121-b12
    1.15  5b8834cc3bb9e24153319c766e04e194945a61b9 jdk8u121-b13
    1.16 +33c7a7def0d76bf508fe4d0a5261027d60bc272f jdk8u121-b31
    1.17 +c946a5cc042f78c054943783d94cdb403c470e8f jdk8u121-b32
    1.18  2359a73f36ca99ba30aef88a38936f6f4e18e65c jdk8u131-b00
    1.19  bc5500cde753aed78c92e7301548fa1450c9b104 jdk8u131-b01
    1.20  c146d8a61d677fd4d07778d0295b4e88e16a7dd3 jdk8u131-b02
     2.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java	Mon Feb 06 12:17:19 2017 -0800
     2.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/DetailImpl.java	Tue Feb 07 15:33:07 2017 -0800
     2.3 @@ -1,5 +1,5 @@
     2.4  /*
     2.5 - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     2.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     2.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     2.8   *
     2.9   * This code is free software; you can redistribute it and/or modify it
    2.10 @@ -47,13 +47,13 @@
    2.11      public DetailEntry addDetailEntry(Name name) throws SOAPException {
    2.12          DetailEntry entry = createDetailEntry(name);
    2.13          addNode(entry);
    2.14 -        return (DetailEntry) circumventBug5034339(entry);
    2.15 +        return entry;
    2.16      }
    2.17  
    2.18      public DetailEntry addDetailEntry(QName qname) throws SOAPException {
    2.19          DetailEntry entry = createDetailEntry(qname);
    2.20          addNode(entry);
    2.21 -        return (DetailEntry) circumventBug5034339(entry);
    2.22 +        return entry;
    2.23      }
    2.24  
    2.25      protected SOAPElement addElement(Name name) throws SOAPException {
    2.26 @@ -119,28 +119,4 @@
    2.27         return true;
    2.28     }
    2.29  
    2.30 -    //overriding this method since the only two uses of this method
    2.31 -    // are in ElementImpl and DetailImpl
    2.32 -    //whereas the original base impl does the correct job for calls to it inside ElementImpl
    2.33 -    // But it would not work for DetailImpl.
    2.34 -    protected SOAPElement circumventBug5034339(SOAPElement element) {
    2.35 -
    2.36 -        Name elementName = element.getElementName();
    2.37 -        if (!isNamespaceQualified(elementName)) {
    2.38 -            String prefix = elementName.getPrefix();
    2.39 -            String defaultNamespace = getNamespaceURI(prefix);
    2.40 -            if (defaultNamespace != null) {
    2.41 -                Name newElementName =
    2.42 -                    NameImpl.create(
    2.43 -                        elementName.getLocalName(),
    2.44 -                        elementName.getPrefix(),
    2.45 -                        defaultNamespace);
    2.46 -                SOAPElement newElement = createDetailEntry(newElementName);
    2.47 -                replaceChild(newElement, element);
    2.48 -                return newElement;
    2.49 -            }
    2.50 -        }
    2.51 -        return element;
    2.52 -    }
    2.53 -
    2.54  }
     3.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java	Mon Feb 06 12:17:19 2017 -0800
     3.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/messaging/saaj/soap/impl/ElementImpl.java	Tue Feb 07 15:33:07 2017 -0800
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -127,8 +127,11 @@
    3.11      }
    3.12  
    3.13      public SOAPElement addChildElement(String localName) throws SOAPException {
    3.14 -        return (SOAPElement) addChildElement(
    3.15 -            NameImpl.createFromUnqualifiedName(localName));
    3.16 +        String nsUri = getNamespaceURI("");
    3.17 +        Name name = (nsUri == null || nsUri.isEmpty())
    3.18 +                ?  NameImpl.createFromUnqualifiedName(localName)
    3.19 +                :  NameImpl.createFromQualifiedName(localName, nsUri);
    3.20 +        return addChildElement(name);
    3.21      }
    3.22  
    3.23      public SOAPElement addChildElement(String localName, String prefix)
    3.24 @@ -372,13 +375,13 @@
    3.25      protected SOAPElement addElement(Name name) throws SOAPException {
    3.26          SOAPElement newElement = createElement(name);
    3.27          addNode(newElement);
    3.28 -        return circumventBug5034339(newElement);
    3.29 +        return newElement;
    3.30      }
    3.31  
    3.32      protected SOAPElement addElement(QName name) throws SOAPException {
    3.33          SOAPElement newElement = createElement(name);
    3.34          addNode(newElement);
    3.35 -        return circumventBug5034339(newElement);
    3.36 +        return newElement;
    3.37      }
    3.38  
    3.39      protected SOAPElement createElement(Name name) {
    3.40 @@ -1201,26 +1204,6 @@
    3.41          return !"".equals(name.getNamespaceURI());
    3.42      }
    3.43  
    3.44 -    protected SOAPElement circumventBug5034339(SOAPElement element) {
    3.45 -
    3.46 -        Name elementName = element.getElementName();
    3.47 -        if (!isNamespaceQualified(elementName)) {
    3.48 -            String prefix = elementName.getPrefix();
    3.49 -            String defaultNamespace = getNamespaceURI(prefix);
    3.50 -            if (defaultNamespace != null) {
    3.51 -                Name newElementName =
    3.52 -                    NameImpl.create(
    3.53 -                        elementName.getLocalName(),
    3.54 -                        elementName.getPrefix(),
    3.55 -                        defaultNamespace);
    3.56 -                SOAPElement newElement = createElement(newElementName);
    3.57 -                replaceChild(newElement, element);
    3.58 -                return newElement;
    3.59 -            }
    3.60 -        }
    3.61 -        return element;
    3.62 -    }
    3.63 -
    3.64      //TODO: This is a temporary SAAJ workaround for optimizing XWS
    3.65      // should be removed once the corresponding JAXP bug is fixed
    3.66      // It appears the bug will be fixed in JAXP 1.4 (not by Appserver 9 timeframe)
     4.1 --- a/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java	Mon Feb 06 12:17:19 2017 -0800
     4.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/api/message/saaj/SaajStaxWriter.java	Tue Feb 07 15:33:07 2017 -0800
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -25,8 +25,10 @@
    4.11  
    4.12  package com.sun.xml.internal.ws.api.message.saaj;
    4.13  
    4.14 +import java.util.Iterator;
    4.15  import java.util.Arrays;
    4.16 -import java.util.Iterator;
    4.17 +import java.util.List;
    4.18 +import java.util.LinkedList;
    4.19  
    4.20  import javax.xml.namespace.NamespaceContext;
    4.21  import javax.xml.namespace.QName;
    4.22 @@ -42,6 +44,17 @@
    4.23  /**
    4.24   * SaajStaxWriter builds a SAAJ SOAPMessage by using XMLStreamWriter interface.
    4.25   *
    4.26 + * <p>
    4.27 + * Defers creation of SOAPElement until all the aspects of the name of the element are known.
    4.28 + * In some cases, the namespace uri is indicated only by the {@link #writeNamespace(String, String)} call.
    4.29 + * After opening an element ({@code writeStartElement}, {@code writeEmptyElement} methods), all attributes
    4.30 + * and namespace assignments are retained within {@link DeferredElement} object ({@code deferredElement} field).
    4.31 + * As soon as any other method than {@code writeAttribute}, {@code writeNamespace}, {@code writeDefaultNamespace}
    4.32 + * or {@code setNamespace} is called, the contents of {@code deferredElement} is transformed into new SOAPElement
    4.33 + * (which is appropriately inserted into the SOAPMessage under construction).
    4.34 + * This mechanism is necessary to fix JDK-8159058 issue.
    4.35 + * </p>
    4.36 + *
    4.37   * @author shih-chang.chen@oracle.com
    4.38   */
    4.39  public class SaajStaxWriter implements XMLStreamWriter {
    4.40 @@ -49,6 +62,7 @@
    4.41      protected SOAPMessage soap;
    4.42      protected String envURI;
    4.43      protected SOAPElement currentElement;
    4.44 +    protected DeferredElement deferredElement;
    4.45  
    4.46      static final protected String Envelope = "Envelope";
    4.47      static final protected String Header = "Header";
    4.48 @@ -59,6 +73,7 @@
    4.49          soap = msg;
    4.50          currentElement = soap.getSOAPPart().getEnvelope();
    4.51          envURI = currentElement.getNamespaceURI();
    4.52 +        this.deferredElement = new DeferredElement();
    4.53      }
    4.54  
    4.55      public SOAPMessage getSOAPMessage() {
    4.56 @@ -67,11 +82,8 @@
    4.57  
    4.58      @Override
    4.59      public void writeStartElement(final String localName) throws XMLStreamException {
    4.60 -        try {
    4.61 -            currentElement = currentElement.addChildElement(localName);
    4.62 -        } catch (SOAPException e) {
    4.63 -            throw new XMLStreamException(e);
    4.64 -        }
    4.65 +        currentElement = deferredElement.flushTo(currentElement);
    4.66 +        deferredElement.setLocalName(localName);
    4.67      }
    4.68  
    4.69      @Override
    4.70 @@ -81,8 +93,10 @@
    4.71  
    4.72      @Override
    4.73      public void writeStartElement(final String prefix, final String ln, final String ns) throws XMLStreamException {
    4.74 -        try {
    4.75 -            if (envURI.equals(ns)) {
    4.76 +        currentElement = deferredElement.flushTo(currentElement);
    4.77 +
    4.78 +        if (envURI.equals(ns)) {
    4.79 +            try {
    4.80                  if (Envelope.equals(ln)) {
    4.81                      currentElement = soap.getSOAPPart().getEnvelope();
    4.82                      fixPrefix(prefix);
    4.83 @@ -96,13 +110,16 @@
    4.84                      fixPrefix(prefix);
    4.85                      return;
    4.86                  }
    4.87 +            } catch (SOAPException e) {
    4.88 +                throw new XMLStreamException(e);
    4.89              }
    4.90 -            currentElement = (prefix == null) ?
    4.91 -                    currentElement.addChildElement(new QName(ns, ln)) :
    4.92 -                    currentElement.addChildElement(ln, prefix, ns);
    4.93 -        } catch (SOAPException e) {
    4.94 -            throw new XMLStreamException(e);
    4.95 +
    4.96          }
    4.97 +
    4.98 +        deferredElement.setLocalName(ln);
    4.99 +        deferredElement.setNamespaceUri(ns);
   4.100 +        deferredElement.setPrefix(prefix);
   4.101 +
   4.102      }
   4.103  
   4.104      private void fixPrefix(final String prfx) throws XMLStreamException {
   4.105 @@ -129,11 +146,13 @@
   4.106  
   4.107      @Override
   4.108      public void writeEndElement() throws XMLStreamException {
   4.109 +        currentElement = deferredElement.flushTo(currentElement);
   4.110          if (currentElement != null) currentElement = currentElement.getParentElement();
   4.111      }
   4.112  
   4.113      @Override
   4.114      public void writeEndDocument() throws XMLStreamException {
   4.115 +        currentElement = deferredElement.flushTo(currentElement);
   4.116      }
   4.117  
   4.118      @Override
   4.119 @@ -151,19 +170,14 @@
   4.120  
   4.121      @Override
   4.122      public void writeAttribute(final String prefix, final String ns, final String ln, final String value) throws XMLStreamException {
   4.123 -        try {
   4.124 -            if (ns == null) {
   4.125 -                if (prefix == null && xmlns.equals(ln)) {
   4.126 -                    currentElement.addNamespaceDeclaration("", value);
   4.127 -                } else {
   4.128 -                    currentElement.setAttributeNS("", ln, value);
   4.129 -                }
   4.130 +        if (ns == null && prefix == null && xmlns.equals(ln)) {
   4.131 +            writeNamespace("", value);
   4.132 +        } else {
   4.133 +            if (deferredElement.isInitialized()) {
   4.134 +                deferredElement.addAttribute(prefix, ns, ln, value);
   4.135              } else {
   4.136 -                QName name = (prefix == null) ? new QName(ns, ln) : new QName(ns, ln, prefix);
   4.137 -                currentElement.addAttribute(name, value);
   4.138 +                addAttibuteToElement(currentElement, prefix, ns, ln, value);
   4.139              }
   4.140 -        } catch (SOAPException e) {
   4.141 -            throw new XMLStreamException(e);
   4.142          }
   4.143      }
   4.144  
   4.145 @@ -174,16 +188,16 @@
   4.146  
   4.147      @Override
   4.148      public void writeNamespace(String prefix, final String uri) throws XMLStreamException {
   4.149 -
   4.150          // make prefix default if null or "xmlns" (according to javadoc)
   4.151 -        if (prefix == null || "xmlns".equals(prefix)) {
   4.152 -            prefix = "";
   4.153 -        }
   4.154 -
   4.155 -        try {
   4.156 -            currentElement.addNamespaceDeclaration(prefix, uri);
   4.157 -        } catch (SOAPException e) {
   4.158 -            throw new XMLStreamException(e);
   4.159 +        String thePrefix = prefix == null || "xmlns".equals(prefix) ? "" : prefix;
   4.160 +        if (deferredElement.isInitialized()) {
   4.161 +            deferredElement.addNamespaceDeclaration(thePrefix, uri);
   4.162 +        } else {
   4.163 +            try {
   4.164 +                currentElement.addNamespaceDeclaration(thePrefix, uri);
   4.165 +            } catch (SOAPException e) {
   4.166 +                throw new XMLStreamException(e);
   4.167 +            }
   4.168          }
   4.169      }
   4.170  
   4.171 @@ -194,35 +208,40 @@
   4.172  
   4.173      @Override
   4.174      public void writeComment(final String data) throws XMLStreamException {
   4.175 +        currentElement = deferredElement.flushTo(currentElement);
   4.176          Comment c = soap.getSOAPPart().createComment(data);
   4.177          currentElement.appendChild(c);
   4.178      }
   4.179  
   4.180      @Override
   4.181      public void writeProcessingInstruction(final String target) throws XMLStreamException {
   4.182 +        currentElement = deferredElement.flushTo(currentElement);
   4.183          Node n = soap.getSOAPPart().createProcessingInstruction(target, "");
   4.184          currentElement.appendChild(n);
   4.185      }
   4.186  
   4.187      @Override
   4.188      public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
   4.189 +        currentElement = deferredElement.flushTo(currentElement);
   4.190          Node n = soap.getSOAPPart().createProcessingInstruction(target, data);
   4.191          currentElement.appendChild(n);
   4.192      }
   4.193  
   4.194      @Override
   4.195      public void writeCData(final String data) throws XMLStreamException {
   4.196 +        currentElement = deferredElement.flushTo(currentElement);
   4.197          Node n = soap.getSOAPPart().createCDATASection(data);
   4.198          currentElement.appendChild(n);
   4.199      }
   4.200  
   4.201      @Override
   4.202      public void writeDTD(final String dtd) throws XMLStreamException {
   4.203 -        //TODO ... Don't do anything here
   4.204 +        currentElement = deferredElement.flushTo(currentElement);
   4.205      }
   4.206  
   4.207      @Override
   4.208      public void writeEntityRef(final String name) throws XMLStreamException {
   4.209 +        currentElement = deferredElement.flushTo(currentElement);
   4.210          Node n = soap.getSOAPPart().createEntityReference(name);
   4.211          currentElement.appendChild(n);
   4.212      }
   4.213 @@ -250,6 +269,7 @@
   4.214  
   4.215      @Override
   4.216      public void writeCharacters(final String text) throws XMLStreamException {
   4.217 +        currentElement = deferredElement.flushTo(currentElement);
   4.218          try {
   4.219              currentElement.addTextNode(text);
   4.220          } catch (SOAPException e) {
   4.221 @@ -259,6 +279,7 @@
   4.222  
   4.223      @Override
   4.224      public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
   4.225 +        currentElement = deferredElement.flushTo(currentElement);
   4.226          char[] chr = (start == 0 && len == text.length) ? text : Arrays.copyOfRange(text, start, start + len);
   4.227          try {
   4.228              currentElement.addTextNode(new String(chr));
   4.229 @@ -274,10 +295,16 @@
   4.230  
   4.231      @Override
   4.232      public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
   4.233 -        try {
   4.234 -            this.currentElement.addNamespaceDeclaration(prefix, uri);
   4.235 -        } catch (SOAPException e) {
   4.236 -            throw new XMLStreamException(e);
   4.237 +        // TODO: this in fact is not what would be expected from XMLStreamWriter
   4.238 +        //       (e.g. XMLStreamWriter for writing to output stream does not write anything as result of
   4.239 +        //        this method, it just rememebers that given prefix is associated with the given uri
   4.240 +        //        for the scope; to actually declare the prefix assignment in the resulting XML, one
   4.241 +        //        needs to call writeNamespace(...) method
   4.242 +        // Kept for backwards compatibility reasons - this might be worth of further investigation.
   4.243 +        if (deferredElement.isInitialized()) {
   4.244 +            deferredElement.addNamespaceDeclaration(prefix, uri);
   4.245 +        } else {
   4.246 +            throw new XMLStreamException("Namespace not associated with any element");
   4.247          }
   4.248      }
   4.249  
   4.250 @@ -308,12 +335,12 @@
   4.251                  return currentElement.lookupPrefix(namespaceURI);
   4.252              }
   4.253              public Iterator getPrefixes(final String namespaceURI) {
   4.254 -                return new Iterator() {
   4.255 +                return new Iterator<String>() {
   4.256                      String prefix = getPrefix(namespaceURI);
   4.257                      public boolean hasNext() {
   4.258                          return (prefix != null);
   4.259                      }
   4.260 -                    public Object next() {
   4.261 +                    public String next() {
   4.262                          if (!hasNext()) throw new java.util.NoSuchElementException();
   4.263                          String next = prefix;
   4.264                          prefix = null;
   4.265 @@ -324,4 +351,209 @@
   4.266              }
   4.267          };
   4.268      }
   4.269 +
   4.270 +    static void addAttibuteToElement(SOAPElement element, String prefix, String ns, String ln, String value)
   4.271 +            throws XMLStreamException {
   4.272 +        try {
   4.273 +            if (ns == null) {
   4.274 +                element.setAttributeNS("", ln, value);
   4.275 +            } else {
   4.276 +                QName name = prefix == null ? new QName(ns, ln) : new QName(ns, ln, prefix);
   4.277 +                element.addAttribute(name, value);
   4.278 +            }
   4.279 +        } catch (SOAPException e) {
   4.280 +            throw new XMLStreamException(e);
   4.281 +        }
   4.282 +    }
   4.283 +
   4.284 +    /**
   4.285 +     * Holds details of element that needs to be deferred in order to manage namespace assignments correctly.
   4.286 +     *
   4.287 +     * <p>
   4.288 +     * An instance of can be set with all the aspects of the element name (local name, prefix, namespace uri).
   4.289 +     * Attributes and namespace declarations (special case of attribute) can be added.
   4.290 +     * Namespace declarations are handled so that the element namespace is updated if it is implied by the namespace
   4.291 +     * declaration and the namespace was not set to non-{@code null} value previously.
   4.292 +     * </p>
   4.293 +     *
   4.294 +     * <p>
   4.295 +     * The state of this object can be {@link #flushTo(SOAPElement) flushed} to SOAPElement - new SOAPElement will
   4.296 +     * be added a child element; the new element will have exactly the shape as represented by the state of this
   4.297 +     * object. Note that the {@link #flushTo(SOAPElement)} method does nothing
   4.298 +     * (and returns the argument immediately) if the state of this object is not initialized
   4.299 +     * (i.e. local name is null).
   4.300 +     * </p>
   4.301 +     *
   4.302 +     * @author ondrej.cerny@oracle.com
   4.303 +     */
   4.304 +    static class DeferredElement {
   4.305 +        private String prefix;
   4.306 +        private String localName;
   4.307 +        private String namespaceUri;
   4.308 +        private final List<NamespaceDeclaration> namespaceDeclarations;
   4.309 +        private final List<AttributeDeclaration> attributeDeclarations;
   4.310 +
   4.311 +        DeferredElement() {
   4.312 +            this.namespaceDeclarations = new LinkedList<NamespaceDeclaration>();
   4.313 +            this.attributeDeclarations = new LinkedList<AttributeDeclaration>();
   4.314 +            reset();
   4.315 +        }
   4.316 +
   4.317 +
   4.318 +        /**
   4.319 +         * Set prefix of the element.
   4.320 +         * @param prefix namespace prefix
   4.321 +         */
   4.322 +        public void setPrefix(final String prefix) {
   4.323 +            this.prefix = prefix;
   4.324 +        }
   4.325 +
   4.326 +        /**
   4.327 +         * Set local name of the element.
   4.328 +         *
   4.329 +         * <p>
   4.330 +         *     This method initializes the element.
   4.331 +         * </p>
   4.332 +         *
   4.333 +         * @param localName local name {@code not null}
   4.334 +         */
   4.335 +        public void setLocalName(final String localName) {
   4.336 +            if (localName == null) {
   4.337 +                throw new IllegalArgumentException("localName can not be null");
   4.338 +            }
   4.339 +            this.localName = localName;
   4.340 +        }
   4.341 +
   4.342 +        /**
   4.343 +         * Set namespace uri.
   4.344 +         *
   4.345 +         * @param namespaceUri namespace uri
   4.346 +         */
   4.347 +        public void setNamespaceUri(final String namespaceUri) {
   4.348 +            this.namespaceUri = namespaceUri;
   4.349 +        }
   4.350 +
   4.351 +        /**
   4.352 +         * Adds namespace prefix assignment to the element.
   4.353 +         *
   4.354 +         * @param prefix prefix (not {@code null})
   4.355 +         * @param namespaceUri namespace uri
   4.356 +         */
   4.357 +        public void addNamespaceDeclaration(final String prefix, final String namespaceUri) {
   4.358 +            if (null == this.namespaceUri && null != namespaceUri && prefix.equals(emptyIfNull(this.prefix))) {
   4.359 +                this.namespaceUri = namespaceUri;
   4.360 +            }
   4.361 +            this.namespaceDeclarations.add(new NamespaceDeclaration(prefix, namespaceUri));
   4.362 +        }
   4.363 +
   4.364 +        /**
   4.365 +         * Adds attribute to the element.
   4.366 +         * @param prefix prefix
   4.367 +         * @param ns namespace
   4.368 +         * @param ln local name
   4.369 +         * @param value value
   4.370 +         */
   4.371 +        public void addAttribute(final String prefix, final String ns, final String ln, final String value) {
   4.372 +            if (ns == null && prefix == null && xmlns.equals(ln)) {
   4.373 +                this.addNamespaceDeclaration(prefix, value);
   4.374 +            } else {
   4.375 +                this.attributeDeclarations.add(new AttributeDeclaration(prefix, ns, ln, value));
   4.376 +            }
   4.377 +        }
   4.378 +
   4.379 +        /**
   4.380 +         * Flushes state of this element to the {@code target} element.
   4.381 +         *
   4.382 +         * <p>
   4.383 +         * If this element is initialized then it is added with all the namespace declarations and attributes
   4.384 +         * to the {@code target} element as a child. The state of this element is reset to uninitialized.
   4.385 +         * The newly added element object is returned.
   4.386 +         * </p>
   4.387 +         * <p>
   4.388 +         * If this element is not initialized then the {@code target} is returned immediately, nothing else is done.
   4.389 +         * </p>
   4.390 +         *
   4.391 +         * @param target target element
   4.392 +         * @return {@code target} or new element
   4.393 +         * @throws XMLStreamException on error
   4.394 +         */
   4.395 +        public SOAPElement flushTo(final SOAPElement target) throws XMLStreamException {
   4.396 +            try {
   4.397 +                if (this.localName != null) {
   4.398 +                    // add the element appropriately (based on namespace declaration)
   4.399 +                    final SOAPElement newElement;
   4.400 +                    if (this.namespaceUri == null) {
   4.401 +                        // add element with inherited scope
   4.402 +                        newElement = target.addChildElement(this.localName);
   4.403 +                    } else if (prefix == null) {
   4.404 +                        newElement = target.addChildElement(new QName(this.namespaceUri, this.localName));
   4.405 +                    } else {
   4.406 +                        newElement = target.addChildElement(this.localName, this.prefix, this.namespaceUri);
   4.407 +                    }
   4.408 +                    // add namespace declarations
   4.409 +                    for (NamespaceDeclaration namespace : this.namespaceDeclarations) {
   4.410 +                        target.addNamespaceDeclaration(namespace.prefix, namespace.namespaceUri);
   4.411 +                    }
   4.412 +                    // add attribute declarations
   4.413 +                    for (AttributeDeclaration attribute : this.attributeDeclarations) {
   4.414 +                        addAttibuteToElement(newElement,
   4.415 +                                attribute.prefix, attribute.namespaceUri, attribute.localName, attribute.value);
   4.416 +                    }
   4.417 +                    // reset state
   4.418 +                    this.reset();
   4.419 +
   4.420 +                    return newElement;
   4.421 +                } else {
   4.422 +                    return target;
   4.423 +                }
   4.424 +                // else after reset state -> not initialized
   4.425 +            } catch (SOAPException e) {
   4.426 +                throw new XMLStreamException(e);
   4.427 +            }
   4.428 +        }
   4.429 +
   4.430 +        /**
   4.431 +         * Is the element initialized?
   4.432 +         * @return boolean indicating whether it was initialized after last flush
   4.433 +         */
   4.434 +        public boolean isInitialized() {
   4.435 +            return this.localName != null;
   4.436 +        }
   4.437 +
   4.438 +        private void reset() {
   4.439 +            this.localName = null;
   4.440 +            this.prefix = null;
   4.441 +            this.namespaceUri = null;
   4.442 +            this.namespaceDeclarations.clear();
   4.443 +            this.attributeDeclarations.clear();
   4.444 +        }
   4.445 +
   4.446 +        private static String emptyIfNull(String s) {
   4.447 +            return s == null ? "" : s;
   4.448 +        }
   4.449 +    }
   4.450 +
   4.451 +    static class NamespaceDeclaration {
   4.452 +        final String prefix;
   4.453 +        final String namespaceUri;
   4.454 +
   4.455 +        NamespaceDeclaration(String prefix, String namespaceUri) {
   4.456 +            this.prefix = prefix;
   4.457 +            this.namespaceUri = namespaceUri;
   4.458 +        }
   4.459 +    }
   4.460 +
   4.461 +    static class AttributeDeclaration {
   4.462 +        final String prefix;
   4.463 +        final String namespaceUri;
   4.464 +        final String localName;
   4.465 +        final String value;
   4.466 +
   4.467 +        AttributeDeclaration(String prefix, String namespaceUri, String localName, String value) {
   4.468 +            this.prefix = prefix;
   4.469 +            this.namespaceUri = namespaceUri;
   4.470 +            this.localName = localName;
   4.471 +            this.value = value;
   4.472 +        }
   4.473 +    }
   4.474  }

mercurial