1 /*
   2  * Copyright (c) 1997, 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.ws.api.message;
  27 
  28 import com.sun.istack.internal.NotNull;
  29 import com.sun.istack.internal.Nullable;
  30 import com.sun.xml.internal.bind.api.Bridge;
  31 import com.sun.xml.internal.ws.api.BindingID;
  32 import com.sun.xml.internal.ws.api.SOAPVersion;
  33 import com.sun.xml.internal.ws.api.WSBinding;
  34 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
  35 import com.sun.xml.internal.ws.api.model.JavaMethod;
  36 import com.sun.xml.internal.ws.api.model.SEIModel;
  37 import com.sun.xml.internal.ws.api.model.WSDLOperationMapping;
  38 import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
  39 import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundPortType;
  40 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
  41 import com.sun.xml.internal.ws.api.pipe.Codec;
  42 import com.sun.xml.internal.ws.api.pipe.Pipe;
  43 import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
  44 import com.sun.xml.internal.ws.client.dispatch.DispatchImpl;
  45 import com.sun.xml.internal.ws.message.AttachmentSetImpl;
  46 import com.sun.xml.internal.ws.message.StringHeader;
  47 import com.sun.xml.internal.ws.message.jaxb.JAXBMessage;
  48 import com.sun.xml.internal.ws.spi.db.XMLBridge;
  49 import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
  50 import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx;
  51 import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx;
  52 import org.xml.sax.ContentHandler;
  53 import org.xml.sax.ErrorHandler;
  54 import org.xml.sax.SAXException;
  55 import org.xml.sax.SAXParseException;
  56 
  57 import javax.xml.bind.JAXBException;
  58 import javax.xml.bind.Unmarshaller;
  59 import javax.xml.namespace.QName;
  60 import javax.xml.soap.MimeHeaders;
  61 import javax.xml.soap.SOAPException;
  62 import javax.xml.soap.SOAPMessage;
  63 import javax.xml.stream.XMLStreamException;
  64 import javax.xml.stream.XMLStreamReader;
  65 import javax.xml.stream.XMLStreamWriter;
  66 import javax.xml.transform.Source;
  67 import javax.xml.ws.Dispatch;
  68 import javax.xml.ws.WebServiceException;
  69 import java.io.InputStream;
  70 import java.lang.reflect.Method;
  71 import java.lang.reflect.Proxy;
  72 import java.util.List;
  73 import java.util.Map;
  74 import java.util.UUID;
  75 
  76 /**
  77  * Represents a SOAP message.
  78  *
  79  *
  80  * <h2>What is a message?</h2>
  81  * <p>
  82  * A {@link Message} consists of the following:
  83  *
  84  * <ol>
  85  * <li>
  86  *    Random-accessible list of headers.
  87  *    a header is a representation of an element inside
  88  *    &lt;soap:Header>.
  89  *    It can be read multiple times,
  90  *    can be added or removed, but it is not modifiable.
  91  *    See {@link HeaderList} for more about headers.
  92  *
  93  * <li>
  94  *    The payload of the message, which is a representation
  95  *    of an element inside &lt;soap:Body>.
  96  *    the payload is streamed, and therefore it can be
  97  *    only read once (or can be only written to something once.)
  98  *    once a payload is used, a message is said to be <b>consumed</b>.
  99  *    A message {@link #hasPayload() may not have any payload.}
 100  *
 101  * <li>
 102  *    Attachments.
 103  *    TODO: can attachments be streamed? I suspect so.
 104  *    does anyone need to read attachment twice?
 105  *
 106  * </ol>
 107  *
 108  *
 109  * <h2>How does this abstraction work?</h2>
 110  * <p>
 111  * The basic idea behind the {@link Message} is to hide the actual
 112  * data representation. For example, a {@link Message} might be
 113  * constructed on top of an {@link InputStream} from the accepted HTTP connection,
 114  * or it might be constructed on top of a JAXB object as a result
 115  * of the method invocation through {@link Proxy}. There will be
 116  * a {@link Message} implementation for each of those cases.
 117  *
 118  * <p>
 119  * This interface provides a lot of methods that access the payload
 120  * in many different forms, and implementations can implement those
 121  * methods in the best possible way.
 122  *
 123  * <p>
 124  * A particular attention is paid to make sure that a {@link Message}
 125  * object can be constructed on a stream that is not fully read yet.
 126  * We believe this improves the turn-around time on the server side.
 127  *
 128  * <p>
 129  * It is often useful to wrap a {@link Message} into another {@link Message},
 130  * for example to encrypt the body, or to verify the signature as the body
 131  * is read.
 132  *
 133  * <p>
 134  * This representation is also used for a REST-ful XML message.
 135  * In such case we'll construct a {@link Message} with empty
 136  * attachments and headers, and when serializing all headers
 137  * and attachments will be ignored.
 138  *
 139  *
 140  *
 141  * <h2>Message and XOP</h2>
 142  * <p>
 143  * XOP is considered as an {@link Codec}, and therefore when you are looking at
 144  * {@link Message}, you'll never see &lt;xop:Include> or any such elements
 145  * (instead you'll see the base64 data inlined.) If a consumer of infoset isn't
 146  * interested in handling XOP by himself, this allows him to work with XOP
 147  * correctly even without noticing it.
 148  *
 149  * <p>
 150  * For producers and consumers that are interested in accessing the binary data
 151  * more efficiently, they can use {@link XMLStreamReaderEx} and
 152  * {@link XMLStreamWriterEx}.
 153  *
 154  *
 155  *
 156  * <h2>Message lifespan</h2>
 157  * <p>
 158  * Often {@link Packet} include information local to a particular
 159  * invocaion (such as {@code HttpServletRequest}, from this angle, it makes sense
 160  * to tie a lifespan of a message to one pipeline invocation.
 161  * <p>
 162  * On the other hand, if you think about WS-RM, it often needs to hold on to
 163  * a message longer than a pipeline invocation (you might get an HTTP request,
 164  * get a message X, get a second HTTP request, get another message Y, and
 165  * only then you might want to process X.)
 166  * <p>
 167  * TODO: what do we do about this?
 168  *
 169  *
 170  * <pre>
 171  * TODO: can body element have foreign attributes? maybe ID for security?
 172  *       Yes, when the SOAP body is signed there will be an ID attribute present
 173  *       But in this case any security based impl may need access
 174  *       to the concrete representation.
 175  * TODO: HTTP headers?
 176  *       Yes. Abstracted as transport-based properties.
 177  * TODO: who handles SOAP 1.1 and SOAP 1.2 difference?
 178  *       As separate channel implementations responsible for the creation of the
 179  *       message?
 180  * TODO: session?
 181  * TODO: Do we need to expose SOAPMessage explicitly?
 182  *       SOAPMessage could be the concrete representation but is it necessary to
 183  *       transform between different concrete representations?
 184  *       Perhaps this comes down to how use channels for creation and processing.
 185  * TODO: Do we need to distinguish better between creation and processing?
 186  *       Do we really need the requirement that a created message can be resused
 187  *       for processing. Shall we bifurcate?
 188  *
 189  * TODO: SOAP version issue
 190  *       SOAP version is determined by the context, so message itself doesn't carry it around (?)
 191  *
 192  * TODO: wrapping message needs easier. in particular properties and attachments.
 193  * </pre>
 194  *
 195  * @author Kohsuke Kawaguchi
 196  */
 197 public abstract class Message {
 198 
 199     // See Packet for doc.
 200     private boolean isProtocolMessage = false;
 201     // next two are package protected - should only be used from Packet
 202     boolean  isProtocolMessage() { return isProtocolMessage; }
 203     void  setIsProtocolMessage() { isProtocolMessage = true; }
 204 
 205     /**
 206      * Returns true if headers are present in the message.
 207      *
 208      * @return
 209      *      true if headers are present.
 210      */
 211     public abstract boolean hasHeaders();
 212 
 213     /**
 214      * Gets all the headers of this message.
 215      *
 216      * <h3>Implementation Note</h3>
 217      * <p>
 218      * {@link Message} implementation is allowed to defer
 219      * the construction of {@link MessageHeaders} object. So
 220      * if you only want to check for the existence of any header
 221      * element, use {@link #hasHeaders()}.
 222      *
 223      * @return
 224      *      always return the same non-null object.
 225      */
 226     public abstract @NotNull MessageHeaders getHeaders();
 227 
 228     /**
 229      * Gets the attachments of this message
 230      * (attachments live outside a message.)
 231      */
 232     public @NotNull AttachmentSet getAttachments() {
 233         if (attachmentSet == null) {
 234             attachmentSet = new AttachmentSetImpl();
 235         }
 236         return attachmentSet;
 237     }
 238 
 239     /**
 240      * Optimization hint for the derived class to check
 241      * if we may have some attachments.
 242      */
 243     protected boolean hasAttachments() {
 244         return attachmentSet!=null;
 245     }
 246 
 247     protected AttachmentSet attachmentSet;
 248 
 249     private WSDLBoundOperation operation = null;
 250 
 251     private WSDLOperationMapping wsdlOperationMapping = null;
 252 
 253     private MessageMetadata messageMetadata = null;
 254 
 255     public void setMessageMedadata(MessageMetadata metadata) {
 256         messageMetadata = metadata;
 257     }
 258 
 259 
 260     /**
 261      * Returns the operation of which this message is an instance of.
 262      *
 263      * <p>
 264      * This method relies on {@link WSDLBoundPortType#getOperation(String, String)} but
 265      * it does so in an efficient way.
 266      *
 267      * @deprecated  It is not always possible to uniquely identify the WSDL Operation from just the
 268      * information in the Message. Instead, Use {@link com.sun.xml.internal.ws.api.message.Packet#getWSDLOperation()}
 269      * to get it correctly.
 270      *
 271      * <p>
 272      * This method works only for a request. A pipe can determine an operation for a request,
 273      * and then keep it in a local variable to use it with a response, so there should be
 274      * no need to find out operation from a response (besides, there might not be any response!).
 275      *
 276      * @param boundPortType
 277      *      This represents the port for which this message is used.
 278      *      Most {@link Pipe}s should get this information when they are created,
 279      *      since a pippeline always work against a particular type of {@link WSDLPort}.
 280      *
 281      * @return
 282      *      Null if the operation was not found. This is possible, for example when a protocol
 283      *      message is sent through a pipeline, or when we receive an invalid request on the server,
 284      *      or when we are on the client and the user appliation sends a random DOM through
 285      *      {@link Dispatch}, so this error needs to be handled gracefully.
 286      */
 287     @Deprecated
 288     public final @Nullable WSDLBoundOperation getOperation(@NotNull WSDLBoundPortType boundPortType) {
 289         if (operation == null && messageMetadata != null) {
 290             if (wsdlOperationMapping == null) wsdlOperationMapping = messageMetadata.getWSDLOperationMapping();
 291             if (wsdlOperationMapping != null) operation = wsdlOperationMapping.getWSDLBoundOperation();
 292         }
 293         if(operation==null)
 294             operation = boundPortType.getOperation(getPayloadNamespaceURI(),getPayloadLocalPart());
 295         return operation;
 296     }
 297 
 298     /**
 299      * The same as {@link #getOperation(WSDLBoundPortType)} but
 300      * takes {@link WSDLPort} for convenience.
 301      *
 302      * @deprecated  It is not always possible to uniquely identify the WSDL Operation from just the
 303      * information in the Message. Instead, Use {@link com.sun.xml.internal.ws.api.message.Packet#getWSDLOperation()}
 304      * to get it correctly.
 305      */
 306     @Deprecated
 307     public final @Nullable WSDLBoundOperation getOperation(@NotNull WSDLPort port) {
 308         return getOperation(port.getBinding());
 309     }
 310 
 311     /**
 312      * Returns the java Method of which this message is an instance of.
 313      *
 314      * It is not always possible to uniquely identify the WSDL Operation from just the
 315      * information in the Message. Instead, Use {@link com.sun.xml.internal.ws.api.message.Packet#getWSDLOperation()}
 316      * to get the QName of the associated wsdl operation correctly.
 317      *
 318      * <p>
 319      * This method works only for a request. A pipe can determine a {@link Method}
 320      * for a request, and then keep it in a local variable to use it with a response,
 321      * so there should be no need to find out operation from a response (besides,
 322      * there might not be any response!).
 323      *
 324      * @param seiModel
 325      *      This represents the java model for the endpoint
 326      *      Some server {@link Pipe}s would get this information when they are created.
 327      *
 328      * @return
 329      *      Null if there is no corresponding Method for this message. This is
 330      *      possible, for example when a protocol message is sent through a
 331      *      pipeline, or when we receive an invalid request on the server,
 332      *      or when we are on the client and the user appliation sends a random
 333      *      DOM through {@link Dispatch}, so this error needs to be handled
 334      *      gracefully.
 335      */
 336     @Deprecated
 337     public final @Nullable JavaMethod getMethod(@NotNull SEIModel seiModel) {
 338         if (wsdlOperationMapping == null && messageMetadata != null) {
 339             wsdlOperationMapping = messageMetadata.getWSDLOperationMapping();
 340         }
 341         if (wsdlOperationMapping != null) {
 342             return wsdlOperationMapping.getJavaMethod();
 343         }
 344         //fall back to the original logic which could be incorrect ...
 345         String localPart = getPayloadLocalPart();
 346         String nsUri;
 347         if (localPart == null) {
 348             localPart = "";
 349             nsUri = "";
 350         } else {
 351             nsUri = getPayloadNamespaceURI();
 352         }
 353         QName name = new QName(nsUri, localPart);
 354         return seiModel.getJavaMethod(name);
 355     }
 356 
 357     private Boolean isOneWay;
 358 
 359     /**
 360      * Returns true if this message is a request message for a
 361      * one way operation according to the given WSDL. False otherwise.
 362      *
 363      * <p>
 364      * This method is functionally equivalent as doing
 365      * {@code getOperation(port).getOperation().isOneWay()}
 366      * (with proper null check and all.) But this method
 367      * can sometimes work faster than that (for example,
 368      * on the client side when used with SEI.)
 369      *
 370      * @param port
 371      *      {@link Message}s are always created under the context of
 372      *      one {@link WSDLPort} and they never go outside that context.
 373      *      Pass in that "governing" {@link WSDLPort} object here.
 374      *      We chose to receive this as a parameter instead of
 375      *      keeping {@link WSDLPort} in a message, just to save the storage.
 376      *
 377      *      <p>
 378      *      The implementation of this method involves caching the return
 379      *      value, so the behavior is undefined if multiple callers provide
 380      *      different {@link WSDLPort} objects, which is a bug of the caller.
 381      */
 382     public boolean isOneWay(@NotNull WSDLPort port) {
 383         if(isOneWay==null) {
 384             // we don't know, so compute.
 385             WSDLBoundOperation op = getOperation(port);
 386             if(op!=null)
 387                 isOneWay = op.getOperation().isOneWay();
 388             else
 389                 // the contract is to return true only when it's known to be one way.
 390                 isOneWay = false;
 391         }
 392         return isOneWay;
 393     }
 394 
 395     /**
 396      * Makes an assertion that this {@link Message} is
 397      * a request message for an one-way operation according
 398      * to the context WSDL.
 399      *
 400      * <p>
 401      * This method is really only intended to be invoked from within
 402      * the JAX-WS runtime, and not by any code building on top of it.
 403      *
 404      * <p>
 405      * This method can be invoked only when the caller "knows" what
 406      * WSDL says. Also, there's no point in invoking this method if the caller
 407      * is doing  {@code getOperation(port).getOperation().isOneWay()},
 408      * or sniffing the payload tag name.
 409      * In particular, this includes {@link DispatchImpl}.
 410      *
 411      * <p>
 412      * Once called, this allows {@link #isOneWay(WSDLPort)} method
 413      * to return a value quickly.
 414      *
 415      * @see #isOneWay(WSDLPort)
 416      */
 417     public final void assertOneWay(boolean value) {
 418         // if two callers make different assertions, that's a bug.
 419         // this is an assertion, not a runtime check because
 420         // nobody outside JAX-WS should be using this.
 421         assert isOneWay==null || isOneWay==value;
 422 
 423         isOneWay = value;
 424     }
 425 
 426 
 427     /**
 428      * Gets the local name of the payload element.
 429      *
 430      * @return
 431      *      null if a {@link Message} doesn't have any payload.
 432      */
 433     public abstract @Nullable String getPayloadLocalPart();
 434 
 435     /**
 436      * Gets the namespace URI of the payload element.
 437      *
 438      * @return
 439      *      null if a {@link Message} doesn't have any payload.
 440      */
 441     public abstract String getPayloadNamespaceURI();
 442     // I'm not putting @Nullable on it because doing null check on getPayloadLocalPart() should be suffice
 443 
 444     /**
 445      * Returns true if a {@link Message} has a payload.
 446      *
 447      * <p>
 448      * A message without a payload is a SOAP message that looks like:
 449      * <pre><xmp>
 450      * <S:Envelope>
 451      *   <S:Header>
 452      *     ...
 453      *   </S:Header>
 454      *   <S:Body />
 455      * </S:Envelope>
 456      * </xmp></pre>
 457      */
 458     public abstract boolean hasPayload();
 459 
 460     /**
 461      * Returns true if this message is a fault.
 462      *
 463      * <p>
 464      * Just a convenience method built on {@link #getPayloadNamespaceURI()}
 465      * and {@link #getPayloadLocalPart()}.
 466      */
 467     public boolean isFault() {
 468         // TODO: is SOAP version a property of a Message?
 469         // or is it defined by external factors?
 470         // how do I compare?
 471         String localPart = getPayloadLocalPart();
 472         if(localPart==null || !localPart.equals("Fault"))
 473             return false;
 474 
 475         String nsUri = getPayloadNamespaceURI();
 476         return nsUri.equals(SOAPVersion.SOAP_11.nsUri) || nsUri.equals(SOAPVersion.SOAP_12.nsUri);
 477     }
 478 
 479     /**
 480      * It gives S:Envelope/S:Body/S:Fault/detail 's first child's name. Should
 481      * be called for messages that have SOAP Fault.
 482      *
 483      * <p> This implementation is expensive so concrete implementations are
 484      * expected to override this one.
 485      *
 486      * @return first detail entry's name, if there is one
 487      *         else null
 488      */
 489     public @Nullable QName getFirstDetailEntryName() {
 490         assert isFault();
 491         Message msg = copy();
 492         try {
 493             SOAPFaultBuilder fault = SOAPFaultBuilder.create(msg);
 494             return fault.getFirstDetailEntryName();
 495         } catch (JAXBException e) {
 496             throw new WebServiceException(e);
 497         }
 498     }
 499 
 500     /**
 501      * Consumes this message including the envelope.
 502      * returns it as a {@link Source} object.
 503      */
 504     public abstract Source readEnvelopeAsSource();
 505 
 506 
 507     /**
 508      * Returns the payload as a {@link Source} object.
 509      *
 510      * This consumes the message.
 511      *
 512      * @return
 513      *      if there's no payload, this method returns null.
 514      */
 515     public abstract Source readPayloadAsSource();
 516 
 517     /**
 518      * Creates the equivalent {@link SOAPMessage} from this message.
 519      *
 520      * This consumes the message.
 521      *
 522      * @throws SOAPException
 523      *      if there's any error while creating a {@link SOAPMessage}.
 524      */
 525     public abstract SOAPMessage readAsSOAPMessage() throws SOAPException;
 526 
 527     /**
 528      * Creates the equivalent {@link SOAPMessage} from this message. It also uses
 529      * transport specific headers from Packet during the SOAPMessage construction
 530      * so that {@link SOAPMessage#getMimeHeaders()} gives meaningful transport
 531      * headers.
 532      *
 533      * This consumes the message.
 534      *
 535      * @throws SOAPException
 536      *      if there's any error while creating a {@link SOAPMessage}.
 537      */
 538     public SOAPMessage readAsSOAPMessage(Packet packet, boolean inbound) throws SOAPException {
 539         return readAsSOAPMessage();
 540     }
 541 
 542     public static Map<String, List<String>> getTransportHeaders(Packet packet) {
 543         return getTransportHeaders(packet, packet.getState().isInbound());
 544     }
 545 
 546     public static Map<String, List<String>> getTransportHeaders(Packet packet, boolean inbound) {
 547         Map<String, List<String>> headers = null;
 548         String key = inbound ? Packet.INBOUND_TRANSPORT_HEADERS : Packet.OUTBOUND_TRANSPORT_HEADERS;
 549         if (packet.supports(key)) {
 550             headers = (Map<String, List<String>>)packet.get(key);
 551         }
 552         return headers;
 553     }
 554 
 555     public static void addSOAPMimeHeaders(MimeHeaders mh, Map<String, List<String>> headers) {
 556         for(Map.Entry<String, List<String>> e : headers.entrySet()) {
 557             if (!e.getKey().equalsIgnoreCase("Content-Type")) {
 558                 for(String value : e.getValue()) {
 559                     mh.addHeader(e.getKey(), value);
 560                 }
 561             }
 562         }
 563     }
 564     /**
 565      * Reads the payload as a JAXB object by using the given unmarshaller.
 566      *
 567      * This consumes the message.
 568      *
 569      * @throws JAXBException
 570      *      If JAXB reports an error during the processing.
 571      */
 572     public abstract <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException;
 573 
 574     /**
 575      * Reads the payload as a JAXB object according to the given {@link Bridge}.
 576      *
 577      * This consumes the message.
 578      *
 579      * @deprecated
 580      * @return null
 581      *      if there's no payload.
 582      * @throws JAXBException
 583      *      If JAXB reports an error during the processing.
 584      */
 585     public abstract <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException;
 586 
 587     /**
 588      * Reads the payload as a Data-Bond object
 589      *
 590      * This consumes the message.
 591      *
 592      * @return null
 593      *      if there's no payload.
 594      * @throws JAXBException
 595      *      If JAXB reports an error during the processing.
 596      */
 597     public abstract <T> T readPayloadAsJAXB(XMLBridge<T> bridge) throws JAXBException;
 598 
 599     /**
 600      * Reads the payload as a {@link XMLStreamReader}
 601      *
 602      * This consumes the message. The caller is encouraged to call
 603      * {@link XMLStreamReaderFactory#recycle(XMLStreamReader)} when finished using
 604      * the instance.
 605      *
 606      * @return
 607      *      If there's no payload, this method returns null.
 608      *      Otherwise always non-null valid {@link XMLStreamReader} that points to
 609      *      the payload tag name.
 610      */
 611     public abstract XMLStreamReader readPayload() throws XMLStreamException;
 612 
 613     /**
 614      * Marks the message as consumed, without actually reading the contents.
 615      *
 616      * <p>
 617      * This method provides an opportunity for implementations to reuse
 618      * any reusable resources needed for representing the payload.
 619      *
 620      * <p>
 621      * This method may not be called more than once since it may have
 622      * released the reusable resources.
 623      */
 624     public void consume() {}
 625 
 626     /**
 627      * Writes the payload to StAX.
 628      *
 629      * This method writes just the payload of the message to the writer.
 630      * This consumes the message.
 631      * The implementation will not write
 632      * {@link XMLStreamWriter#writeStartDocument()}
 633      * nor
 634      * {@link XMLStreamWriter#writeEndDocument()}
 635      *
 636      * <p>
 637      * If there's no payload, this method is no-op.
 638      *
 639      * @throws XMLStreamException
 640      *      If the {@link XMLStreamWriter} reports an error,
 641      *      or some other errors happen during the processing.
 642      */
 643     public abstract void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException;
 644 
 645     /**
 646      * Writes the whole SOAP message (but not attachments)
 647      * to the given writer.
 648      *
 649      * This consumes the message.
 650      *
 651      * @throws XMLStreamException
 652      *      If the {@link XMLStreamWriter} reports an error,
 653      *      or some other errors happen during the processing.
 654      */
 655     public abstract void writeTo(XMLStreamWriter sw) throws XMLStreamException;
 656 
 657     /**
 658      * Writes the whole SOAP envelope as SAX events.
 659      *
 660      * <p>
 661      * This consumes the message.
 662      *
 663      * @param contentHandler
 664      *      must not be nulll.
 665      * @param errorHandler
 666      *      must not be null.
 667      *      any error encountered during the SAX event production must be
 668      *      first reported to this error handler. Fatal errors can be then
 669      *      thrown as {@link SAXParseException}. {@link SAXException}s thrown
 670      *      from {@link ErrorHandler} should propagate directly through this method.
 671      */
 672     public abstract void writeTo( ContentHandler contentHandler, ErrorHandler errorHandler ) throws SAXException;
 673 
 674     // TODO: do we need a method that reads payload as a fault?
 675     // do we want a separte streaming representation of fault?
 676     // or would SOAPFault in SAAJ do?
 677 
 678 
 679 
 680     /**
 681      * Creates a copy of a {@link Message}.
 682      *
 683      * <p>
 684      * This method creates a new {@link Message} whose header/payload/attachments/properties
 685      * are identical to this {@link Message}. Once created, the created {@link Message}
 686      * and the original {@link Message} behaves independently --- adding header/
 687      * attachment to one {@link Message} doesn't affect another {@link Message}
 688      * at all.
 689      *
 690      * <p>
 691      * This method does <b>NOT</b> consume a message.
 692      *
 693      * <p>
 694      * To enable efficient copy operations, there's a few restrictions on
 695      * how copied message can be used.
 696      *
 697      * <ol>
 698      *  <li>The original and the copy may not be
 699      *      used concurrently by two threads (this allows two {@link Message}s
 700      *      to share some internal resources, such as JAXB marshallers.)
 701      *      Note that it's OK for the original and the copy to be processed
 702      *      by two threads, as long as they are not concurrent.
 703      *
 704      *  <li>The copy has the same 'life scope'
 705      *      as the original (this allows shallower copy, such as
 706      *      JAXB beans wrapped in {@link JAXBMessage}.)
 707      * </ol>
 708      *
 709      * <p>
 710      * A 'life scope' of a message created during a message processing
 711      * in a pipeline is until a pipeline processes the next message.
 712      * A message cannot be kept beyond its life scope.
 713      *
 714      * (This experimental design is to allow message objects to be reused
 715      * --- feedback appreciated.)
 716      *
 717      *
 718      *
 719      * <h3>Design Rationale</h3>
 720      * <p>
 721      * Since a {@link Message} body is read-once, sometimes
 722      * (such as when you do fail-over, or WS-RM) you need to
 723      * create an idential copy of a {@link Message}.
 724      *
 725      * <p>
 726      * The actual copy operation depends on the layout
 727      * of the data in memory, hence it's best to be done by
 728      * the {@link Message} implementation itself.
 729      *
 730      * <p>
 731      * The restrictions placed on the use of copied {@link Message} can be
 732      * relaxed if necessary, but it will make the copy method more expensive.
 733      *
 734      * <h3>IMPORTANT</h3>
 735      * <p> WHEN YOU IMPLEMENT OR CHANGE A {@link .copy()} METHOD, YOU MUST
 736      * USE THE {@link copyFrom(Message)} METHOD IN THE IMPLEMENTATION.
 737      */
 738     // TODO: update the class javadoc with 'lifescope'
 739     // and move the discussion about life scope there.
 740     public abstract Message copy();
 741 
 742     /**
 743      * The {@link Message#copy()} method is used as a shorthand
 744      * throughout the codecase in place of calling a copy constructor.
 745      * However, that shorthand make it difficult to have a concrete
 746      * method here in the base to do common work.
 747      *
 748      * <p> Rather than have each {@code copy} method duplicate code, the
 749      * following method is used in each {@code copy} implementation.
 750      * It MUST be called.
 751      *
 752      * @return The Message that calls {@code copyFrom} inside the
 753      * {@code copy} method after the copy constructor
 754      */
 755     public final Message copyFrom(Message m) {
 756         isProtocolMessage = m.isProtocolMessage;
 757         return this;
 758     }
 759 
 760     /**
 761      * Retuns a unique id for the message. The id can be used for various things,
 762      * like debug assistance, logging, and MIME encoding(say for boundary).
 763      *
 764      * <p>
 765      * This method will check the existence of the addressing <MessageID> header,
 766      * and if present uses that value. Otherwise it generates one from UUID.random(),
 767      * and return it without adding a new header. But it doesn't add a <MessageID>
 768      * to the header list since we expect them to be added before calling this
 769      * method.
 770      *
 771      * <p>
 772      * Addressing tube will go do a separate verification on inbound
 773      * headers to make sure that <MessageID> header is present when it's
 774      * supposed to be.
 775      *
 776      * @param binding object created by {@link BindingID#createBinding()}
 777      *
 778      * @return unique id for the message
 779      * @deprecated
 780      */
 781     public @NotNull String getID(@NotNull WSBinding binding) {
 782         return getID(binding.getAddressingVersion(), binding.getSOAPVersion());
 783     }
 784 
 785     /**
 786      * Retuns a unique id for the message.
 787      * <p><p>
 788      * @see {@link #getID(com.sun.xml.internal.ws.api.WSBinding)} for detailed description.
 789      * @param av WS-Addressing version
 790      * @param sv SOAP version
 791      * @return unique id for the message
 792      * @deprecated
 793      */
 794     public @NotNull String getID(AddressingVersion av, SOAPVersion sv) {
 795         String uuid = null;
 796         if (av != null) {
 797             uuid = AddressingUtils.getMessageID(getHeaders(), av, sv);
 798         }
 799         if (uuid == null) {
 800             uuid = generateMessageID();
 801             getHeaders().add(new StringHeader(av.messageIDTag, uuid));
 802         }
 803         return uuid;
 804     }
 805 
 806     /**
 807      * Generates a UUID suitable for use as a MessageID value
 808      * @return generated UUID
 809      */
 810     public static String generateMessageID() {
 811         return "uuid:" + UUID.randomUUID().toString();
 812     }
 813 
 814     public SOAPVersion getSOAPVersion() {
 815         return null;
 816     }
 817 }