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
26package com.sun.xml.internal.ws.api.message;
27
28import com.sun.istack.internal.NotNull;
29import com.sun.istack.internal.Nullable;
30import com.sun.xml.internal.bind.api.Bridge;
31import com.sun.xml.internal.ws.api.BindingID;
32import com.sun.xml.internal.ws.api.SOAPVersion;
33import com.sun.xml.internal.ws.api.WSBinding;
34import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
35import com.sun.xml.internal.ws.api.model.JavaMethod;
36import com.sun.xml.internal.ws.api.model.SEIModel;
37import com.sun.xml.internal.ws.api.model.WSDLOperationMapping;
38import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
39import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundPortType;
40import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
41import com.sun.xml.internal.ws.api.pipe.Codec;
42import com.sun.xml.internal.ws.api.pipe.Pipe;
43import com.sun.xml.internal.ws.api.streaming.XMLStreamReaderFactory;
44import com.sun.xml.internal.ws.client.dispatch.DispatchImpl;
45import com.sun.xml.internal.ws.message.AttachmentSetImpl;
46import com.sun.xml.internal.ws.message.StringHeader;
47import com.sun.xml.internal.ws.message.jaxb.JAXBMessage;
48import com.sun.xml.internal.ws.spi.db.XMLBridge;
49import com.sun.xml.internal.ws.fault.SOAPFaultBuilder;
50import com.sun.xml.internal.org.jvnet.staxex.XMLStreamReaderEx;
51import com.sun.xml.internal.org.jvnet.staxex.XMLStreamWriterEx;
52import org.xml.sax.ContentHandler;
53import org.xml.sax.ErrorHandler;
54import org.xml.sax.SAXException;
55import org.xml.sax.SAXParseException;
56
57import javax.xml.bind.JAXBException;
58import javax.xml.bind.Unmarshaller;
59import javax.xml.namespace.QName;
60import javax.xml.soap.MimeHeaders;
61import javax.xml.soap.SOAPException;
62import javax.xml.soap.SOAPMessage;
63import javax.xml.stream.XMLStreamException;
64import javax.xml.stream.XMLStreamReader;
65import javax.xml.stream.XMLStreamWriter;
66import javax.xml.transform.Source;
67import javax.xml.ws.Dispatch;
68import javax.xml.ws.WebServiceException;
69import java.io.InputStream;
70import java.lang.reflect.Method;
71import java.lang.reflect.Proxy;
72import java.util.List;
73import java.util.Map;
74import 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 */
197public 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>{@code
450     * <S:Envelope>
451     *   <S:Header>
452     *     ...
453     *   </S:Header>
454     *   <S:Body />
455     * </S:Envelope>
456     * }</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}
818