View Javadoc
1   /*
2    * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.xml.internal.ws.api.message;
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     /**
200      * Returns true if headers are present in the message.
201      *
202      * @return
203      *      true if headers are present.
204      */
205     public abstract boolean hasHeaders();
206 
207     /**
208      * Gets all the headers of this message.
209      *
210      * <h3>Implementation Note</h3>
211      * <p>
212      * {@link Message} implementation is allowed to defer
213      * the construction of {@link MessageHeaders} object. So
214      * if you only want to check for the existence of any header
215      * element, use {@link #hasHeaders()}.
216      *
217      * @return
218      *      always return the same non-null object.
219      */
220     public abstract @NotNull MessageHeaders getHeaders();
221 
222     /**
223      * Gets the attachments of this message
224      * (attachments live outside a message.)
225      */
226     public @NotNull AttachmentSet getAttachments() {
227         if (attachmentSet == null) {
228             attachmentSet = new AttachmentSetImpl();
229         }
230         return attachmentSet;
231     }
232 
233     /**
234      * Optimization hint for the derived class to check
235      * if we may have some attachments.
236      */
237     protected boolean hasAttachments() {
238         return attachmentSet!=null;
239     }
240 
241     protected AttachmentSet attachmentSet;
242 
243     private WSDLBoundOperation operation = null;
244 
245     private WSDLOperationMapping wsdlOperationMapping = null;
246 
247     private MessageMetadata messageMetadata = null;
248 
249     public void setMessageMedadata(MessageMetadata metadata) {
250         messageMetadata = metadata;
251     }
252 
253 
254     /**
255      * Returns the operation of which this message is an instance of.
256      *
257      * <p>
258      * This method relies on {@link WSDLBoundPortType#getOperation(String, String)} but
259      * it does so in an efficient way.
260      *
261      * @deprecated  It is not always possible to uniquely identify the WSDL Operation from just the
262      * information in the Message. Instead, Use {@link com.sun.xml.internal.ws.api.message.Packet#getWSDLOperation()}
263      * to get it correctly.
264      *
265      * <p>
266      * This method works only for a request. A pipe can determine an operation for a request,
267      * and then keep it in a local variable to use it with a response, so there should be
268      * no need to find out operation from a response (besides, there might not be any response!).
269      *
270      * @param boundPortType
271      *      This represents the port for which this message is used.
272      *      Most {@link Pipe}s should get this information when they are created,
273      *      since a pippeline always work against a particular type of {@link WSDLPort}.
274      *
275      * @return
276      *      Null if the operation was not found. This is possible, for example when a protocol
277      *      message is sent through a pipeline, or when we receive an invalid request on the server,
278      *      or when we are on the client and the user appliation sends a random DOM through
279      *      {@link Dispatch}, so this error needs to be handled gracefully.
280      */
281     @Deprecated
282     public final @Nullable WSDLBoundOperation getOperation(@NotNull WSDLBoundPortType boundPortType) {
283         if (operation == null && messageMetadata != null) {
284             if (wsdlOperationMapping == null) wsdlOperationMapping = messageMetadata.getWSDLOperationMapping();
285             if (wsdlOperationMapping != null) operation = wsdlOperationMapping.getWSDLBoundOperation();
286         }
287         if(operation==null)
288             operation = boundPortType.getOperation(getPayloadNamespaceURI(),getPayloadLocalPart());
289         return operation;
290     }
291 
292     /**
293      * The same as {@link #getOperation(WSDLBoundPortType)} but
294      * takes {@link WSDLPort} for convenience.
295      *
296      * @deprecated  It is not always possible to uniquely identify the WSDL Operation from just the
297      * information in the Message. Instead, Use {@link com.sun.xml.internal.ws.api.message.Packet#getWSDLOperation()}
298      * to get it correctly.
299      */
300     @Deprecated
301     public final @Nullable WSDLBoundOperation getOperation(@NotNull WSDLPort port) {
302         return getOperation(port.getBinding());
303     }
304 
305     /**
306      * Returns the java Method of which this message is an instance of.
307      *
308      * It is not always possible to uniquely identify the WSDL Operation from just the
309      * information in the Message. Instead, Use {@link com.sun.xml.internal.ws.api.message.Packet#getWSDLOperation()}
310      * to get the QName of the associated wsdl operation correctly.
311      *
312      * <p>
313      * This method works only for a request. A pipe can determine a {@link Method}
314      * for a request, and then keep it in a local variable to use it with a response,
315      * so there should be no need to find out operation from a response (besides,
316      * there might not be any response!).
317      *
318      * @param seiModel
319      *      This represents the java model for the endpoint
320      *      Some server {@link Pipe}s would get this information when they are created.
321      *
322      * @return
323      *      Null if there is no corresponding Method for this message. This is
324      *      possible, for example when a protocol message is sent through a
325      *      pipeline, or when we receive an invalid request on the server,
326      *      or when we are on the client and the user appliation sends a random
327      *      DOM through {@link Dispatch}, so this error needs to be handled
328      *      gracefully.
329      */
330     @Deprecated
331     public final @Nullable JavaMethod getMethod(@NotNull SEIModel seiModel) {
332         if (wsdlOperationMapping == null && messageMetadata != null) {
333             wsdlOperationMapping = messageMetadata.getWSDLOperationMapping();
334         }
335         if (wsdlOperationMapping != null) {
336             return wsdlOperationMapping.getJavaMethod();
337         }
338         //fall back to the original logic which could be incorrect ...
339         String localPart = getPayloadLocalPart();
340         String nsUri;
341         if (localPart == null) {
342             localPart = "";
343             nsUri = "";
344         } else {
345             nsUri = getPayloadNamespaceURI();
346         }
347         QName name = new QName(nsUri, localPart);
348         return seiModel.getJavaMethod(name);
349     }
350 
351     private Boolean isOneWay;
352 
353     /**
354      * Returns true if this message is a request message for a
355      * one way operation according to the given WSDL. False otherwise.
356      *
357      * <p>
358      * This method is functionally equivalent as doing
359      * {@code getOperation(port).getOperation().isOneWay()}
360      * (with proper null check and all.) But this method
361      * can sometimes work faster than that (for example,
362      * on the client side when used with SEI.)
363      *
364      * @param port
365      *      {@link Message}s are always created under the context of
366      *      one {@link WSDLPort} and they never go outside that context.
367      *      Pass in that "governing" {@link WSDLPort} object here.
368      *      We chose to receive this as a parameter instead of
369      *      keeping {@link WSDLPort} in a message, just to save the storage.
370      *
371      *      <p>
372      *      The implementation of this method involves caching the return
373      *      value, so the behavior is undefined if multiple callers provide
374      *      different {@link WSDLPort} objects, which is a bug of the caller.
375      */
376     public boolean isOneWay(@NotNull WSDLPort port) {
377         if(isOneWay==null) {
378             // we don't know, so compute.
379             WSDLBoundOperation op = getOperation(port);
380             if(op!=null)
381                 isOneWay = op.getOperation().isOneWay();
382             else
383                 // the contract is to return true only when it's known to be one way.
384                 isOneWay = false;
385         }
386         return isOneWay;
387     }
388 
389     /**
390      * Makes an assertion that this {@link Message} is
391      * a request message for an one-way operation according
392      * to the context WSDL.
393      *
394      * <p>
395      * This method is really only intended to be invoked from within
396      * the JAX-WS runtime, and not by any code building on top of it.
397      *
398      * <p>
399      * This method can be invoked only when the caller "knows" what
400      * WSDL says. Also, there's no point in invoking this method if the caller
401      * is doing  {@code getOperation(port).getOperation().isOneWay()},
402      * or sniffing the payload tag name.
403      * In particular, this includes {@link DispatchImpl}.
404      *
405      * <p>
406      * Once called, this allows {@link #isOneWay(WSDLPort)} method
407      * to return a value quickly.
408      *
409      * @see #isOneWay(WSDLPort)
410      */
411     public final void assertOneWay(boolean value) {
412         // if two callers make different assertions, that's a bug.
413         // this is an assertion, not a runtime check because
414         // nobody outside JAX-WS should be using this.
415         assert isOneWay==null || isOneWay==value;
416 
417         isOneWay = value;
418     }
419 
420 
421     /**
422      * Gets the local name of the payload element.
423      *
424      * @return
425      *      null if a {@link Message} doesn't have any payload.
426      */
427     public abstract @Nullable String getPayloadLocalPart();
428 
429     /**
430      * Gets the namespace URI of the payload element.
431      *
432      * @return
433      *      null if a {@link Message} doesn't have any payload.
434      */
435     public abstract String getPayloadNamespaceURI();
436     // I'm not putting @Nullable on it because doing null check on getPayloadLocalPart() should be suffice
437 
438     /**
439      * Returns true if a {@link Message} has a payload.
440      *
441      * <p>
442      * A message without a payload is a SOAP message that looks like:
443      * <pre><xmp>
444      * <S:Envelope>
445      *   <S:Header>
446      *     ...
447      *   </S:Header>
448      *   <S:Body />
449      * </S:Envelope>
450      * </xmp></pre>
451      */
452     public abstract boolean hasPayload();
453 
454     /**
455      * Returns true if this message is a fault.
456      *
457      * <p>
458      * Just a convenience method built on {@link #getPayloadNamespaceURI()}
459      * and {@link #getPayloadLocalPart()}.
460      */
461     public boolean isFault() {
462         // TODO: is SOAP version a property of a Message?
463         // or is it defined by external factors?
464         // how do I compare?
465         String localPart = getPayloadLocalPart();
466         if(localPart==null || !localPart.equals("Fault"))
467             return false;
468 
469         String nsUri = getPayloadNamespaceURI();
470         return nsUri.equals(SOAPVersion.SOAP_11.nsUri) || nsUri.equals(SOAPVersion.SOAP_12.nsUri);
471     }
472 
473     /**
474      * It gives S:Envelope/S:Body/S:Fault/detail 's first child's name. Should
475      * be called for messages that have SOAP Fault.
476      *
477      * <p> This implementation is expensive so concrete implementations are
478      * expected to override this one.
479      *
480      * @return first detail entry's name, if there is one
481      *         else null
482      */
483     public @Nullable QName getFirstDetailEntryName() {
484         assert isFault();
485         Message msg = copy();
486         try {
487             SOAPFaultBuilder fault = SOAPFaultBuilder.create(msg);
488             return fault.getFirstDetailEntryName();
489         } catch (JAXBException e) {
490             throw new WebServiceException(e);
491         }
492     }
493 
494     /**
495      * Consumes this message including the envelope.
496      * returns it as a {@link Source} object.
497      */
498     public abstract Source readEnvelopeAsSource();
499 
500 
501     /**
502      * Returns the payload as a {@link Source} object.
503      *
504      * This consumes the message.
505      *
506      * @return
507      *      if there's no payload, this method returns null.
508      */
509     public abstract Source readPayloadAsSource();
510 
511     /**
512      * Creates the equivalent {@link SOAPMessage} from this message.
513      *
514      * This consumes the message.
515      *
516      * @throws SOAPException
517      *      if there's any error while creating a {@link SOAPMessage}.
518      */
519     public abstract SOAPMessage readAsSOAPMessage() throws SOAPException;
520 
521     /**
522      * Creates the equivalent {@link SOAPMessage} from this message. It also uses
523      * transport specific headers from Packet during the SOAPMessage construction
524      * so that {@link SOAPMessage#getMimeHeaders()} gives meaningful transport
525      * headers.
526      *
527      * This consumes the message.
528      *
529      * @throws SOAPException
530      *      if there's any error while creating a {@link SOAPMessage}.
531      */
532     public SOAPMessage readAsSOAPMessage(Packet packet, boolean inbound) throws SOAPException {
533         return readAsSOAPMessage();
534     }
535 
536     public static Map<String, List<String>> getTransportHeaders(Packet packet) {
537         return getTransportHeaders(packet, packet.getState().isInbound());
538     }
539 
540     public static Map<String, List<String>> getTransportHeaders(Packet packet, boolean inbound) {
541         Map<String, List<String>> headers = null;
542         String key = inbound ? Packet.INBOUND_TRANSPORT_HEADERS : Packet.OUTBOUND_TRANSPORT_HEADERS;
543         if (packet.supports(key)) {
544             headers = (Map<String, List<String>>)packet.get(key);
545         }
546         return headers;
547     }
548 
549     public static void addSOAPMimeHeaders(MimeHeaders mh, Map<String, List<String>> headers) {
550         for(Map.Entry<String, List<String>> e : headers.entrySet()) {
551             if (!e.getKey().equalsIgnoreCase("Content-Type")) {
552                 for(String value : e.getValue()) {
553                     mh.addHeader(e.getKey(), value);
554                 }
555             }
556         }
557     }
558     /**
559      * Reads the payload as a JAXB object by using the given unmarshaller.
560      *
561      * This consumes the message.
562      *
563      * @throws JAXBException
564      *      If JAXB reports an error during the processing.
565      */
566     public abstract <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException;
567 
568     /**
569      * Reads the payload as a JAXB object according to the given {@link Bridge}.
570      *
571      * This consumes the message.
572      *
573      * @deprecated
574      * @return null
575      *      if there's no payload.
576      * @throws JAXBException
577      *      If JAXB reports an error during the processing.
578      */
579     public abstract <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException;
580 
581     /**
582      * Reads the payload as a Data-Bond object
583      *
584      * This consumes the message.
585      *
586      * @return null
587      *      if there's no payload.
588      * @throws JAXBException
589      *      If JAXB reports an error during the processing.
590      */
591     public abstract <T> T readPayloadAsJAXB(XMLBridge<T> bridge) throws JAXBException;
592 
593     /**
594      * Reads the payload as a {@link XMLStreamReader}
595      *
596      * This consumes the message. The caller is encouraged to call
597      * {@link XMLStreamReaderFactory#recycle(XMLStreamReader)} when finished using
598      * the instance.
599      *
600      * @return
601      *      If there's no payload, this method returns null.
602      *      Otherwise always non-null valid {@link XMLStreamReader} that points to
603      *      the payload tag name.
604      */
605     public abstract XMLStreamReader readPayload() throws XMLStreamException;
606 
607     /**
608      * Marks the message as consumed, without actually reading the contents.
609      *
610      * <p>
611      * This method provides an opportunity for implementations to reuse
612      * any reusable resources needed for representing the payload.
613      *
614      * <p>
615      * This method may not be called more than once since it may have
616      * released the reusable resources.
617      */
618     public void consume() {}
619 
620     /**
621      * Writes the payload to StAX.
622      *
623      * This method writes just the payload of the message to the writer.
624      * This consumes the message.
625      * The implementation will not write
626      * {@link XMLStreamWriter#writeStartDocument()}
627      * nor
628      * {@link XMLStreamWriter#writeEndDocument()}
629      *
630      * <p>
631      * If there's no payload, this method is no-op.
632      *
633      * @throws XMLStreamException
634      *      If the {@link XMLStreamWriter} reports an error,
635      *      or some other errors happen during the processing.
636      */
637     public abstract void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException;
638 
639     /**
640      * Writes the whole SOAP message (but not attachments)
641      * to the given writer.
642      *
643      * This consumes the message.
644      *
645      * @throws XMLStreamException
646      *      If the {@link XMLStreamWriter} reports an error,
647      *      or some other errors happen during the processing.
648      */
649     public abstract void writeTo(XMLStreamWriter sw) throws XMLStreamException;
650 
651     /**
652      * Writes the whole SOAP envelope as SAX events.
653      *
654      * <p>
655      * This consumes the message.
656      *
657      * @param contentHandler
658      *      must not be nulll.
659      * @param errorHandler
660      *      must not be null.
661      *      any error encountered during the SAX event production must be
662      *      first reported to this error handler. Fatal errors can be then
663      *      thrown as {@link SAXParseException}. {@link SAXException}s thrown
664      *      from {@link ErrorHandler} should propagate directly through this method.
665      */
666     public abstract void writeTo( ContentHandler contentHandler, ErrorHandler errorHandler ) throws SAXException;
667 
668     // TODO: do we need a method that reads payload as a fault?
669     // do we want a separte streaming representation of fault?
670     // or would SOAPFault in SAAJ do?
671 
672 
673 
674     /**
675      * Creates a copy of a {@link Message}.
676      *
677      * <p>
678      * This method creates a new {@link Message} whose header/payload/attachments/properties
679      * are identical to this {@link Message}. Once created, the created {@link Message}
680      * and the original {@link Message} behaves independently --- adding header/
681      * attachment to one {@link Message} doesn't affect another {@link Message}
682      * at all.
683      *
684      * <p>
685      * This method does <b>NOT</b> consume a message.
686      *
687      * <p>
688      * To enable efficient copy operations, there's a few restrictions on
689      * how copied message can be used.
690      *
691      * <ol>
692      *  <li>The original and the copy may not be
693      *      used concurrently by two threads (this allows two {@link Message}s
694      *      to share some internal resources, such as JAXB marshallers.)
695      *      Note that it's OK for the original and the copy to be processed
696      *      by two threads, as long as they are not concurrent.
697      *
698      *  <li>The copy has the same 'life scope'
699      *      as the original (this allows shallower copy, such as
700      *      JAXB beans wrapped in {@link JAXBMessage}.)
701      * </ol>
702      *
703      * <p>
704      * A 'life scope' of a message created during a message processing
705      * in a pipeline is until a pipeline processes the next message.
706      * A message cannot be kept beyond its life scope.
707      *
708      * (This experimental design is to allow message objects to be reused
709      * --- feedback appreciated.)
710      *
711      *
712      *
713      * <h3>Design Rationale</h3>
714      * <p>
715      * Since a {@link Message} body is read-once, sometimes
716      * (such as when you do fail-over, or WS-RM) you need to
717      * create an idential copy of a {@link Message}.
718      *
719      * <p>
720      * The actual copy operation depends on the layout
721      * of the data in memory, hence it's best to be done by
722      * the {@link Message} implementation itself.
723      *
724      * <p>
725      * The restrictions placed on the use of copied {@link Message} can be
726      * relaxed if necessary, but it will make the copy method more expensive.
727      */
728     // TODO: update the class javadoc with 'lifescope'
729     // and move the discussion about life scope there.
730     public abstract Message copy();
731 
732     /**
733      * Retuns a unique id for the message. The id can be used for various things,
734      * like debug assistance, logging, and MIME encoding(say for boundary).
735      *
736      * <p>
737      * This method will check the existence of the addressing <MessageID> header,
738      * and if present uses that value. Otherwise it generates one from UUID.random(),
739      * and return it without adding a new header. But it doesn't add a <MessageID>
740      * to the header list since we expect them to be added before calling this
741      * method.
742      *
743      * <p>
744      * Addressing tube will go do a separate verification on inbound
745      * headers to make sure that <MessageID> header is present when it's
746      * supposed to be.
747      *
748      * @param binding object created by {@link BindingID#createBinding()}
749      *
750      * @return unique id for the message
751      * @deprecated
752      */
753     public @NotNull String getID(@NotNull WSBinding binding) {
754         return getID(binding.getAddressingVersion(), binding.getSOAPVersion());
755     }
756 
757     /**
758      * Retuns a unique id for the message.
759      * <p><p>
760      * @see {@link #getID(com.sun.xml.internal.ws.api.WSBinding)} for detailed description.
761      * @param av WS-Addressing version
762      * @param sv SOAP version
763      * @return unique id for the message
764      * @deprecated
765      */
766     public @NotNull String getID(AddressingVersion av, SOAPVersion sv) {
767         String uuid = null;
768         if (av != null) {
769             uuid = AddressingUtils.getMessageID(getHeaders(), av, sv);
770         }
771         if (uuid == null) {
772             uuid = generateMessageID();
773             getHeaders().add(new StringHeader(av.messageIDTag, uuid));
774         }
775         return uuid;
776     }
777 
778     /**
779      * Generates a UUID suitable for use as a MessageID value
780      * @return generated UUID
781      */
782     public static String generateMessageID() {
783         return "uuid:" + UUID.randomUUID().toString();
784     }
785 
786     public SOAPVersion getSOAPVersion() {
787         return null;
788     }
789 }