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

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 397
b99d7e355d4b
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

     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  */
    26 package com.sun.xml.internal.ws.api.message;
    28 import com.oracle.webservices.internal.api.message.ContentType;
    29 import com.oracle.webservices.internal.api.message.PropertySet;
    30 import com.sun.istack.internal.NotNull;
    31 import com.sun.istack.internal.Nullable;
    32 import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
    33 import com.sun.xml.internal.ws.addressing.WsaPropertyBag;
    34 import com.sun.xml.internal.ws.addressing.WsaServerTube;
    35 import com.sun.xml.internal.ws.addressing.WsaTubeHelper;
    36 import com.sun.xml.internal.ws.api.Component;
    37 import com.sun.xml.internal.ws.api.EndpointAddress;
    38 import com.sun.xml.internal.ws.api.SOAPVersion;
    39 import com.sun.xml.internal.ws.api.WSBinding;
    40 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
    41 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
    42 import com.sun.xml.internal.ws.api.model.JavaMethod;
    43 import com.sun.xml.internal.ws.api.model.SEIModel;
    44 import com.sun.xml.internal.ws.api.model.WSDLOperationMapping;
    45 import com.sun.xml.internal.ws.api.model.wsdl.WSDLOperation;
    46 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
    47 import com.sun.xml.internal.ws.api.pipe.Codec;
    48 import com.sun.xml.internal.ws.api.pipe.Tube;
    49 import com.sun.xml.internal.ws.api.server.Adapter;
    50 import com.sun.xml.internal.ws.api.server.TransportBackChannel;
    51 import com.sun.xml.internal.ws.api.server.WSEndpoint;
    52 import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate;
    53 import com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory;
    54 import com.sun.xml.internal.ws.client.*;
    55 import com.sun.xml.internal.ws.developer.JAXWSProperties;
    56 import com.sun.xml.internal.ws.encoding.MtomCodec;
    57 import com.sun.xml.internal.ws.message.RelatesToHeader;
    58 import com.sun.xml.internal.ws.message.StringHeader;
    59 import com.sun.xml.internal.ws.util.DOMUtil;
    60 import com.sun.xml.internal.ws.util.xml.XmlUtil;
    61 import com.sun.xml.internal.ws.wsdl.DispatchException;
    62 import com.sun.xml.internal.ws.wsdl.OperationDispatcher;
    63 import com.sun.xml.internal.ws.resources.AddressingMessages;
    66 import org.w3c.dom.Document;
    67 import org.w3c.dom.Element;
    68 import org.xml.sax.SAXException;
    70 import javax.xml.namespace.QName;
    71 import javax.xml.soap.SOAPException;
    72 import javax.xml.soap.SOAPMessage;
    73 import javax.xml.stream.XMLStreamWriter;
    74 import javax.xml.stream.XMLStreamException;
    75 import javax.xml.ws.BindingProvider;
    76 import javax.xml.ws.Dispatch;
    77 import javax.xml.ws.WebServiceContext;
    78 import javax.xml.ws.WebServiceException;
    79 import javax.xml.ws.handler.LogicalMessageContext;
    80 import javax.xml.ws.handler.MessageContext;
    81 import javax.xml.ws.handler.soap.SOAPMessageContext;
    82 import javax.xml.ws.soap.MTOMFeature;
    84 import java.util.*;
    85 import java.util.logging.Logger;
    86 import java.io.ByteArrayOutputStream;
    87 import java.io.IOException;
    88 import java.io.OutputStream;
    89 import java.nio.channels.WritableByteChannel;
    91 /**
    92  * Represents a container of a {@link Message}.
    93  *
    94  * <h2>What is a {@link Packet}?</h2>
    95  * <p>
    96  * A packet can be thought of as a frame/envelope/package that wraps
    97  * a {@link Message}. A packet keeps track of optional metadata (properties)
    98  * about a {@link Message} that doesn't go across the wire.
    99  * This roughly corresponds to {@link MessageContext} in the JAX-WS API.
   100  *
   101  * <p>
   102  * Usually a packet contains a {@link Message} in it, but sometimes
   103  * (such as for a reply of an one-way operation), a packet may
   104  * float around without a {@link Message} in it.
   105  *
   106  *
   107  * <a name="properties"></a>
   108  * <h2>Properties</h2>
   109  * <p>
   110  * Information frequently used inside the JAX-WS RI
   111  * is stored in the strongly-typed fields. Other information is stored
   112  * in terms of a generic {@link Map} (see
   113  * {@link #invocationProperties}.)
   114  *
   115  * <p>
   116  * Some properties need to be retained between request and response,
   117  * some don't. For strongly typed fields, this characteristic is
   118  * statically known for each of them, and propagation happens accordingly.
   119  * For generic information stored in {@link Map}, {@link #invocationProperties}
   120  * stores per-invocation scope information (which carries over to
   121  * the response.)
   122  *
   123  * <p>
   124  * This object is used as the backing store of {@link MessageContext}, and
   125  * {@link LogicalMessageContext} and {@link SOAPMessageContext} will
   126  * be delegating to this object for storing/retrieving values.
   127  *
   128  *
   129  * <h3>Relationship to request/response context</h3>
   130  * <p>
   131  * {@link BindingProvider#getRequestContext() Request context} is used to
   132  * seed the initial values of {@link Packet}.
   133  * Some of those values go to strongly-typed fields, and others go to
   134  * {@link #invocationProperties}, as they need to be retained in the reply message.
   135  *
   136  * <p>
   137  * Similarly, {@link BindingProvider#getResponseContext() response context}
   138  * is constructed from {@link Packet} (or rather it's just a view of {@link Packet}.)
   139  * by using properties from {@link #invocationProperties},
   140  * modulo properties named explicitly in {@link #getHandlerScopePropertyNames(boolean)}.
   141  * IOW, properties added to {@link #invocationProperties}
   142  * are exposed to the response context by default.
   143  *
   144  *
   145  *
   146  * <h3>TODO</h3>
   147  * <ol>
   148  *  <li>this class needs to be cloneable since Message is copiable.
   149  *  <li>The three live views aren't implemented correctly. It will be
   150  *      more work to do so, although I'm sure it's possible.
   151  *  <li>{@link PropertySet.Property} annotation is to make it easy
   152  *      for {@link MessageContext} to export properties on this object,
   153  *      but it probably needs some clean up.
   154  * </ol>
   155  *
   156  * @author Kohsuke Kawaguchi
   157  */
   158 public final class Packet
   159         // Packet must continue to extend/implement deprecated interfaces until downstream
   160         // usage is updated.
   161     extends com.oracle.webservices.internal.api.message.BaseDistributedPropertySet
   162     implements com.oracle.webservices.internal.api.message.MessageContext, MessageMetadata {
   164     /**
   165      * Creates a {@link Packet} that wraps a given {@link Message}.
   166      *
   167      * <p>
   168      * This method should be only used to create a fresh {@link Packet}.
   169      * To create a {@link Packet} for a reply, use {@link #createResponse(Message)}.
   170      *
   171      * @param request
   172      *      The request {@link Message}. Can be null.
   173      */
   174     public Packet(Message request) {
   175         this();
   176         this.message = request;
   177         if (message != null) message.setMessageMedadata(this);
   178     }
   180     /**
   181      * Creates an empty {@link Packet} that doesn't have any {@link Message}.
   182      */
   183     public Packet() {
   184         this.invocationProperties = new HashMap<String, Object>();
   185     }
   187     /**
   188      * Used by {@link #createResponse(Message)} and {@link #copy(boolean)}.
   189      */
   190     private Packet(Packet that) {
   191         relatePackets(that, true);
   192         this.invocationProperties = that.invocationProperties;
   193     }
   195     /**
   196      * Creates a copy of this {@link Packet}.
   197      *
   198      * @param copyMessage determines whether the {@link Message} from the original {@link Packet} should be copied as
   199      *        well, or not. If the value is {@code false}, the {@link Message} in the copy of the {@link Packet} is {@code null}.
   200      * @return copy of the original packet
   201      */
   202     public Packet copy(boolean copyMessage) {
   203         // the copy constructor is originally designed for creating a response packet,
   204         // but so far the implementation is usable for this purpose as well, so calling the copy constructor
   205         // to avoid code dupliation.
   206         Packet copy = new Packet(this);
   207         if (copyMessage && this.message != null) {
   208             copy.message = this.message.copy();
   209         }
   210         if (copy.message != null) copy.message.setMessageMedadata(copy);
   211         return copy;
   212     }
   214     private Message message;
   216     /**
   217      * Gets the last {@link Message} set through {@link #setMessage(Message)}.
   218      *
   219      * @return may null. See the class javadoc for when it's null.
   220      */
   221     public Message getMessage() {
   222         if (message != null && !(message instanceof MessageWrapper)) {
   223             message = new MessageWrapper(this, message);
   224         }
   225         return  message;
   226     }
   228     public Message getInternalMessage() {
   229         return (message instanceof MessageWrapper)? ((MessageWrapper)message).delegate : message;
   230     }
   232     public WSBinding getBinding() {
   233         if (endpoint != null) {
   234             return endpoint.getBinding();
   235         }
   236         if (proxy != null) {
   237             return (WSBinding) proxy.getBinding();
   238         }
   239         return null;
   240     }
   241     /**
   242      * Sets a {@link Message} to this packet.
   243      *
   244      * @param message Can be null.
   245      */
   246     public void setMessage(Message message) {
   247         this.message = message;
   248         if (message != null) this.message.setMessageMedadata(this);
   249     }
   251     private WSDLOperationMapping wsdlOperationMapping = null;
   253     private QName wsdlOperation;
   255     /**
   256      * Returns the QName of the wsdl operation associated with this packet.
   257      * <p/>
   258      * Information such as Payload QName, wsa:Action header, SOAPAction HTTP header are used depending on the features
   259      * enabled on the particular port.
   260      *
   261      * @return null if there is no WSDL model or
   262      *         runtime cannot uniquely identify the wsdl operation from the information in the packet.
   263      */
   264     @Property(MessageContext.WSDL_OPERATION)
   265     public final
   266     @Nullable
   267     QName getWSDLOperation() {
   268         if (wsdlOperation != null) return wsdlOperation;
   269         if ( wsdlOperationMapping == null)  wsdlOperationMapping = getWSDLOperationMapping();
   270         if ( wsdlOperationMapping != null ) wsdlOperation = wsdlOperationMapping.getOperationName();
   271         return wsdlOperation;
   272     }
   274     public WSDLOperationMapping getWSDLOperationMapping() {
   275         if (wsdlOperationMapping != null) return wsdlOperationMapping;
   276         OperationDispatcher opDispatcher = null;
   277         if (endpoint != null) {
   278             opDispatcher = endpoint.getOperationDispatcher();
   279         } else if (proxy != null) {
   280             opDispatcher = ((Stub) proxy).getOperationDispatcher();
   281         }
   282         //OpDispatcher is null when there is no WSDLModel
   283         if (opDispatcher != null) {
   284             try {
   285                 wsdlOperationMapping = opDispatcher.getWSDLOperationMapping(this);
   286             } catch (DispatchException e) {
   287                 //Ignore, this might be a protocol message which may not have a wsdl operation
   288                 //LOGGER.info("Cannot resolve wsdl operation that this Packet is targeted for.");
   289             }
   290         }
   291         return wsdlOperationMapping;
   292     }
   294     /**
   295      * Set the wsdl operation to avoid lookup from other data.
   296      * This is useful in SEI based clients, where the WSDL operation can be known
   297      * from the associated {@link JavaMethod}
   298      *
   299      * @param wsdlOp QName
   300      */
   301     public void setWSDLOperation(QName wsdlOp) {
   302         this.wsdlOperation = wsdlOp;
   303     }
   305     /**
   306      * True if this message came from a transport (IOW inbound),
   307      * and in paricular from a "secure" transport. A transport
   308      * needs to set this flag appropriately.
   309      *
   310      * <p>
   311      * This is a requirement from the security team.
   312      */
   313     // TODO: expose this as a property
   314     public boolean wasTransportSecure;
   316     /**
   317      * Inbound transport headers are captured in a transport neutral way.
   318      * Transports are expected to fill this data after creating a Packet.
   319      * <p>
   320      * {@link SOAPMessage#getMimeHeaders()} would return these headers.
   321      */
   322     public static final String INBOUND_TRANSPORT_HEADERS = "com.sun.xml.internal.ws.api.message.packet.inbound.transport.headers";
   324     /**
   325      * Outbound transport headers are captured in a transport neutral way.
   326      *
   327      * <p>
   328      * Transports may choose to ignore certain headers that interfere with
   329      * its correct operation, such as
   330      * <tt>Content-Type</tt> and <tt>Content-Length</tt>.
   331      */
   332     public static final String OUTBOUND_TRANSPORT_HEADERS = "com.sun.xml.internal.ws.api.message.packet.outbound.transport.headers";
   334     /**
   335      *
   336      */
   337     public static final String HA_INFO = "com.sun.xml.internal.ws.api.message.packet.hainfo";
   340     /**
   341      * This property holds the snapshot of HandlerConfiguration
   342      * at the time of invocation.
   343      * This property is used by MUPipe and HandlerPipe implementations.
   344      */
   345     @Property(BindingProviderProperties.JAXWS_HANDLER_CONFIG)
   346     public HandlerConfiguration handlerConfig;
   348     /**
   349      * If a message originates from a proxy stub that implements
   350      * a port interface, this field is set to point to that object.
   351      *
   352      * TODO: who's using this property?
   353      */
   354     @Property(BindingProviderProperties.JAXWS_CLIENT_HANDLE_PROPERTY)
   355     public BindingProvider proxy;
   357     /**
   358      * Determines if the governing {@link Adapter} or {@link com.sun.xml.internal.ws.api.pipe.Fiber.CompletionCallback}
   359      * will handle delivering response messages targeted at non-anonymous endpoint
   360      * addresses.  Prior to the introduction of this flag
   361      * the {@link WsaServerTube} would deliver non-anonymous responses.
   362      */
   363     public boolean isAdapterDeliversNonAnonymousResponse;
   365     /**
   366      * During invocation of a client Stub or Dispatch a Packet is
   367      * created then the Stub's RequestContext is copied into the
   368      * Packet.  On certain internal cases the Packet is created
   369      * *before* the invocation.  In those cases we want the contents
   370      * of the Packet to take precedence when ever any key/value pairs
   371      * collide : if the Packet contains a value for a key use it,
   372      * otherwise copy as usual from Stub.
   373      */
   374     public boolean packetTakesPriorityOverRequestContext = false;
   376     /**
   377      * The endpoint address to which this message is sent to.
   378      *
   379      * <p>
   380      * The JAX-WS spec allows this to be changed for each message,
   381      * so it's designed to be a property.
   382      *
   383      * <p>
   384      * Must not be null for a request message on the client. Otherwise
   385      * it's null.
   386      */
   387     public EndpointAddress endpointAddress;
   389     /**
   390      * @deprecated
   391      *      The programatic acccess should be done via
   392      *      {@link #endpointAddress}. This is for JAX-WS client applications
   393      *      that access this property via {@link BindingProvider#ENDPOINT_ADDRESS_PROPERTY}.
   394      */
   395     @Property(BindingProvider.ENDPOINT_ADDRESS_PROPERTY)
   396     public String getEndPointAddressString() {
   397         if (endpointAddress == null) {
   398             return null;
   399         } else {
   400             return endpointAddress.toString();
   401         }
   402     }
   404     public void setEndPointAddressString(String s) {
   405         if (s == null) {
   406             this.endpointAddress = null;
   407         } else {
   408             this.endpointAddress = EndpointAddress.create(s);
   409         }
   410     }
   412     /**
   413      * The value of {@link ContentNegotiation#PROPERTY}
   414      * property.
   415      * <p/>
   416      * This property is used only on the client side.
   417      */
   418     public ContentNegotiation contentNegotiation;
   420     @Property(ContentNegotiation.PROPERTY)
   421     public String getContentNegotiationString() {
   422         return (contentNegotiation != null) ? contentNegotiation.toString() : null;
   423     }
   425     public void setContentNegotiationString(String s) {
   426         if (s == null) {
   427             contentNegotiation = null;
   428         } else {
   429             try {
   430                 contentNegotiation = ContentNegotiation.valueOf(s);
   431             } catch (IllegalArgumentException e) {
   432                 // If the value is not recognized default to none
   433                 contentNegotiation = ContentNegotiation.none;
   434             }
   435         }
   436     }
   438     /**
   439      * Gives a list of Reference Parameters in the Message
   440      * <p>
   441      * Headers which have attribute wsa:IsReferenceParameter="true"
   442      * This is not cached as one may reset the Message.
   443      *<p>
   444      */
   445     @Property(MessageContext.REFERENCE_PARAMETERS)
   446     public
   447     @NotNull
   448     List<Element> getReferenceParameters() {
   449         Message msg = getMessage();
   450         List<Element> refParams = new ArrayList<Element>();
   451         if (msg == null) {
   452             return refParams;
   453         }
   454         MessageHeaders hl = msg.getHeaders();
   455         for (Header h : hl.asList()) {
   456             String attr = h.getAttribute(AddressingVersion.W3C.nsUri, "IsReferenceParameter");
   457             if (attr != null && (attr.equals("true") || attr.equals("1"))) {
   458                 Document d = DOMUtil.createDom();
   459                 SAX2DOMEx s2d = new SAX2DOMEx(d);
   460                 try {
   461                     h.writeTo(s2d, XmlUtil.DRACONIAN_ERROR_HANDLER);
   462                     refParams.add((Element) d.getLastChild());
   463                 } catch (SAXException e) {
   464                     throw new WebServiceException(e);
   465                 }
   466                 /*
   467                 DOMResult result = new DOMResult(d);
   468                 XMLDOMWriterImpl domwriter = new XMLDOMWriterImpl(result);
   469                 try {
   470                     h.writeTo(domwriter);
   471                     refParams.add((Element) result.getNode().getLastChild());
   472                 } catch (XMLStreamException e) {
   473                     throw new WebServiceException(e);
   474                 }
   475                 */
   476             }
   477         }
   478         return refParams;
   479     }
   481     /**
   482      *      This method is for exposing header list through {@link PropertySet#get(Object)},
   483      *      for user applications, and should never be invoked directly from within the JAX-WS RI.
   484      */
   485     @Property(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY)
   486     /*package*/ MessageHeaders getHeaderList() {
   487         Message msg = getMessage();
   488         if (msg == null) {
   489             return null;
   490         }
   491         return msg.getHeaders();
   492     }
   494     /**
   495      * The list of MIME types that are acceptable to a receiver
   496      * of an outbound message.
   497      *
   498      * This property is used only on the server side.
   499      *
   500      * <p>The representation shall be that specified by the HTTP Accept
   501      * request-header field.
   502      *
   503      * <p>The list of content types will be obtained from the transport
   504      * meta-data of a inbound message in a request/response message exchange.
   505      * Hence this property will be set by the service-side transport pipe.
   506      */
   507     public String acceptableMimeTypes;
   509     /**
   510      * When non-null, this object is consulted to
   511      * implement {@link WebServiceContext} methods
   512      * exposed to the user application.
   513      *
   514      * Used only on the server side.
   515      *
   516      * <p>
   517      * This property is set from the parameter
   518      * of {@link WSEndpoint.PipeHead#process}.
   519      */
   520     public WebServiceContextDelegate webServiceContextDelegate;
   522     /**
   523      * Used only on the server side so that the transport
   524      * can close the connection early.
   525      *
   526      * <p>
   527      * This field can be null. While a message is being processed,
   528      * this field can be set explicitly to null, to prevent
   529      * future pipes from closing a transport (see {@link #keepTransportBackChannelOpen()})
   530      *
   531      * <p>
   532      * This property is set from the parameter
   533      * of {@link WSEndpoint.PipeHead#process}.
   534      */
   535     public
   536     @Nullable
   537     TransportBackChannel transportBackChannel;
   539     /**
   540      * Keeps the transport back channel open (by seeting {@link #transportBackChannel} to null.)
   541      *
   542      * @return
   543      *      The previous value of {@link #transportBackChannel}.
   544      */
   545     public TransportBackChannel keepTransportBackChannelOpen() {
   546         TransportBackChannel r = transportBackChannel;
   547         transportBackChannel = null;
   548         return r;
   549     }
   551     /**
   552       * The governing owner of this packet.  On the service-side this is the {@link Adapter} and on the client it is the {@link Stub}.
   553       *
   554       */
   555      public Component component;
   557     /**
   558      * The governing {@link WSEndpoint} in which this message is floating.
   559      *
   560      * <p>
   561      * This property is set if and only if this is on the server side.
   562      */
   563     @Property(JAXWSProperties.WSENDPOINT)
   564     public WSEndpoint endpoint;
   566     /**
   567      * The value of the SOAPAction header associated with the message.
   568      *
   569      * <p>
   570      * For outgoing messages, the transport may sends out this value.
   571      * If this field is null, the transport may choose to send <tt>""</tt>
   572      * (quoted empty string.)
   573      *
   574      * For incoming messages, the transport will set this field.
   575      * If the incoming message did not contain the SOAPAction header,
   576      * the transport sets this field to null.
   577      *
   578      * <p>
   579      * If the value is non-null, it must be always in the quoted form.
   580      * The value can be null.
   581      *
   582      * <p>
   583      * Note that the way the transport sends this value out depends on
   584      * transport and SOAP version.
   585      * <p/>
   586      * For HTTP transport and SOAP 1.1, BP requires that SOAPAction
   587      * header is present (See {@BP R2744} and {@BP R2745}.) For SOAP 1.2,
   588      * this is moved to the parameter of the "application/soap+xml".
   589      */
   590     @Property(BindingProvider.SOAPACTION_URI_PROPERTY)
   591     public String soapAction;
   593     /**
   594      * A hint indicating that whether a transport should expect
   595      * a reply back from the server.
   596      *
   597      * <p>
   598      * This property is used on the client-side for
   599      * outbound messages, so that a pipeline
   600      * can communicate to the terminal (or intermediate) {@link Tube}s
   601      * about this knowledge.
   602      *
   603      * <p>
   604      * This property <b>MUST NOT</b> be used by 2-way transports
   605      * that have the transport back channel. Those transports
   606      * must always check a reply coming through the transport back
   607      * channel regardless of this value, and act accordingly.
   608      * (This is because the expectation of the client and
   609      * that of the server can be different, for example because
   610      * of a bug in user's configuration.)
   611      *
   612      * <p>
   613      * This property is for one-way transports, and more
   614      * specifically for the coordinator that correlates sent requests
   615      * and incoming replies, to decide whether to block
   616      * until a response is received.
   617      *
   618      * <p>
   619      * Also note that this property is related to
   620      * {@link WSDLOperation#isOneWay()} but not the same thing.
   621      * In fact in general, they are completely orthogonal.
   622      *
   623      * For example, the calling application can choose to invoke
   624      * {@link Dispatch#invoke(Object)} or {@link Dispatch#invokeOneWay(Object)}
   625      * with an operation (which determines the value of this property),
   626      * regardless of whether WSDL actually says it's one way or not.
   627      * So these two booleans can take any combinations.
   628      *
   629      *
   630      * <p>
   631      * When this property is {@link Boolean#FALSE}, it means that
   632      * the pipeline does not expect a reply from a server (and therefore
   633      * the correlator should not block for a reply message
   634      * -- if such a reply does arrive, it can be just ignored.)
   635      *
   636      * <p>
   637      * When this property is {@link Boolean#TRUE}, it means that
   638      * the pipeline expects a reply from a server (and therefore
   639      * the correlator should block to see if a reply message is received,
   640      *
   641      * <p>
   642      * This property is always set to {@link Boolean#TRUE} or
   643      * {@link Boolean#FALSE} when used on the request message
   644      * on the client side.
   645      * No other {@link Boolean} instances are allowed.
   646      * <p>
   647      *
   648      * In all other situations, this property is null.
   649      *
   650      */
   651     @Property(BindingProviderProperties.ONE_WAY_OPERATION)
   652     public Boolean expectReply;
   655     /**
   656      * This property will be removed in a near future.
   657      *
   658      * <p>
   659      * A part of what this flag represented moved to
   660      * {@link #expectReply} and the other part was moved
   661      * to {@link Message#isOneWay(WSDLPort)}. Please update
   662      * your code soon, or risk breaking your build!!
   663      */
   664     @Deprecated
   665     public Boolean isOneWay;
   667     /**
   668      * Indicates whether is invoking a synchronous pattern. If true, no
   669      * async client programming model (e.g. AsyncResponse or AsyncHandler)
   670      * were used to make the request that created this packet.
   671      */
   672     public Boolean isSynchronousMEP;
   674     /**
   675      * Indicates whether a non-null AsyncHandler was given at the point of
   676      * making the request that created this packet. This flag can be used
   677      * by Tube implementations to decide how to react when isSynchronousMEP
   678      * is false. If true, the client gave a non-null AsyncHandler instance
   679      * at the point of request, and will be expecting a response on that
   680      * handler when this request has been processed.
   681      */
   682     public Boolean nonNullAsyncHandlerGiven;
   684     /**
   685      * USE-CASE:
   686      * WS-AT is enabled, but there is no WSDL available.
   687      * If Packet.isRequestReplyMEP() is Boolean.TRUE then WS-AT should
   688      * add the TX context.
   689      *
   690      * This value is exposed to users via facades at higher abstraction layers.
   691      * The user should NEVER use Packet directly.
   692      * This value should ONLY be set by users.
   693      */
   694     private Boolean isRequestReplyMEP;
   695     public Boolean isRequestReplyMEP() { return isRequestReplyMEP; }
   696     public void setRequestReplyMEP(final Boolean x) { isRequestReplyMEP = x; }
   698     /**
   699      * Lazily created set of handler-scope property names.
   700      *
   701      * <p>
   702      * We expect that this is only used when handlers are present
   703      * and they explicitly set some handler-scope values.
   704      *
   705      * @see #getHandlerScopePropertyNames(boolean)
   706      */
   707     private Set<String> handlerScopePropertyNames;
   709     /**
   710      * Bag to capture properties that are available for the whole
   711      * message invocation (namely on both requests and responses.)
   712      *
   713      * <p>
   714      * These properties are copied from a request to a response.
   715      * This is where we keep properties that are set by handlers.
   716      *
   717      * <p>
   718      * See <a href="#properties">class javadoc</a> for more discussion.
   719      *
   720      * @see #getHandlerScopePropertyNames(boolean)
   721      */
   722     public final Map<String, Object> invocationProperties;
   724     /**
   725      * Gets a {@link Set} that stores handler-scope properties.
   726      *
   727      * <p>
   728      * These properties will not be exposed to the response context.
   729      * Consequently, if a {@link Tube} wishes to hide a property
   730      * to {@link ResponseContext}, it needs to add the property name
   731      * to this set.
   732      *
   733      * @param readOnly
   734      *      Return true if the caller only intends to read the value of this set.
   735      *      Internally, the {@link Set} is allocated lazily, and this flag helps
   736      *      optimizing the strategy.
   737      *
   738      * @return
   739      *      always non-null, possibly empty set that stores property names.
   740      */
   741     public final Set<String> getHandlerScopePropertyNames(boolean readOnly) {
   742         Set<String> o = this.handlerScopePropertyNames;
   743         if (o == null) {
   744             if (readOnly) {
   745                 return Collections.emptySet();
   746             }
   747             o = new HashSet<String>();
   748             this.handlerScopePropertyNames = o;
   749         }
   750         return o;
   751     }
   753     /**
   754      * This method no longer works.
   755      *
   756      * @deprecated
   757      *      Use {@link #getHandlerScopePropertyNames(boolean)}.
   758      *      To be removed once Tango components are updated.
   759      */
   760     public final Set<String> getApplicationScopePropertyNames(boolean readOnly) {
   761         assert false;
   762         return new HashSet<String>();
   763     }
   765     /**
   766      * Creates a response {@link Packet} from a request packet ({@code this}).
   767      *
   768      * <p>
   769      * When a {@link Packet} for a reply is created, some properties need to be
   770      * copied over from a request to a response, and this method handles it correctly.
   771      *
   772      * @deprecated
   773      *      Use createClientResponse(Message) for client side and
   774      *      createServerResponse(Message, String) for server side response
   775      *      creation.
   776      *
   777      * @param msg
   778      *      The {@link Message} that represents a reply. Can be null.
   779      */
   780     @Deprecated
   781     public Packet createResponse(Message msg) {
   782         Packet response = new Packet(this);
   783         response.setMessage(msg);
   784         return response;
   785     }
   787     /**
   788      * Creates a response {@link Packet} from a request packet ({@code this}).
   789      *
   790      * <p>
   791      * When a {@link Packet} for a reply is created, some properties need to be
   792      * copied over from a request to a response, and this method handles it correctly.
   793      *
   794      * @param msg
   795      *      The {@link Message} that represents a reply. Can be null.
   796      */
   797     public Packet createClientResponse(Message msg) {
   798         Packet response = new Packet(this);
   799         response.setMessage(msg);
   800         finishCreateRelateClientResponse(response);
   801         return response;
   802     }
   804     /**
   805      * For use cases that start with an existing Packet.
   806      */
   807     public Packet relateClientResponse(final Packet response) {
   808         response.relatePackets(this, true);
   809         finishCreateRelateClientResponse(response);
   810         return response;
   811     }
   813     private void finishCreateRelateClientResponse(final Packet response) {
   814         response.soapAction = null; // de-initializing
   815         response.setState(State.ClientResponse);
   816     }
   818     /**
   819      * Creates a server-side response {@link Packet} from a request
   820      * packet ({@code this}). If WS-Addressing is enabled, a default Action
   821      * Message Addressing Property is obtained using <code>wsdlPort</code> {@link WSDLPort}
   822      * and <code>binding</code> {@link WSBinding}.
   823      * <p><p>
   824      * This method should be called to create application response messages
   825      * since they are associated with a {@link WSBinding} and {@link WSDLPort}.
   826      * For creating protocol messages that require a non-default Action, use
   827      * {@link #createServerResponse(Message, com.sun.xml.internal.ws.api.addressing.AddressingVersion, com.sun.xml.internal.ws.api.SOAPVersion, String)}.
   828      *
   829      * @param responseMessage The {@link Message} that represents a reply. Can be null.
   830      * @param wsdlPort The response WSDL port.
   831      * @param binding The response Binding. Cannot be null.
   832      * @return response packet
   833      */
   834     public Packet createServerResponse(@Nullable Message responseMessage, @Nullable WSDLPort wsdlPort, @Nullable SEIModel seiModel, @NotNull WSBinding binding) {
   835         Packet r = createClientResponse(responseMessage);
   836         return relateServerResponse(r, wsdlPort, seiModel, binding);
   837     }
   839     /**
   840      * Copy all properties from ({@code this}) packet into a input {@link Packet}
   841      * @param response packet
   842      */
   843     public void copyPropertiesTo(@Nullable Packet response){
   844         relatePackets(response, false);
   845     }
   848     /**
   849      * A common method to make members related between input packet and this packet
   850      *
   851      * @param packet
   852      * @param isCopy 'true' means copying all properties from input packet;
   853      *               'false' means copying all properties from this packet to input packet.
   854      */
   855     private void relatePackets(@Nullable Packet packet, boolean isCopy)
   856     {
   857         Packet request;
   858             Packet response;
   860         if (!isCopy) { //is relate
   861           request = this;
   862           response = packet;
   864           // processing specific properties
   865           response.soapAction = null;
   866           response.invocationProperties.putAll(request.invocationProperties);
   867           if (this.getState().equals(State.ServerRequest)) {
   868               response.setState(State.ServerResponse);
   869           }
   870         } else { //is copy constructor
   871           request = packet;
   872           response = this;
   874           // processing specific properties
   875           response.soapAction = request.soapAction;
   876           response.setState(request.getState());
   877         }
   879         request.copySatelliteInto(response);
   880         response.isAdapterDeliversNonAnonymousResponse = request.isAdapterDeliversNonAnonymousResponse;
   881         response.handlerConfig = request.handlerConfig;
   882         response.handlerScopePropertyNames = request.handlerScopePropertyNames;
   883         response.contentNegotiation = request.contentNegotiation;
   884         response.wasTransportSecure = request.wasTransportSecure;
   885         response.transportBackChannel = request.transportBackChannel;
   886         response.endpointAddress = request.endpointAddress;
   887         response.wsdlOperation = request.wsdlOperation;
   888         response.wsdlOperationMapping = request.wsdlOperationMapping;
   889         response.acceptableMimeTypes = request.acceptableMimeTypes;
   890         response.endpoint = request.endpoint;
   891         response.proxy = request.proxy;
   892         response.webServiceContextDelegate = request.webServiceContextDelegate;
   893         response.expectReply = request.expectReply;
   894         response.component = request.component;
   895         response.mtomAcceptable = request.mtomAcceptable;
   896         response.mtomRequest = request.mtomRequest;
   897         // copy other properties that need to be copied. is there any?
   898     }
   901     public Packet relateServerResponse(@Nullable Packet r, @Nullable WSDLPort wsdlPort, @Nullable SEIModel seiModel, @NotNull WSBinding binding) {
   902         relatePackets(r, false);
   903         r.setState(State.ServerResponse);
   904         AddressingVersion av = binding.getAddressingVersion();
   905         // populate WS-A headers only if WS-A is enabled
   906         if (av == null) {
   907             return r;
   908         }
   910         if (getMessage() == null) {
   911             return r;
   912         }
   914         //populate WS-A headers only if the request has addressing headers
   915         String inputAction = AddressingUtils.getAction(getMessage().getHeaders(), av, binding.getSOAPVersion());
   916         if (inputAction == null) {
   917             return r;
   918         }
   919         // if one-way, then dont populate any WS-A headers
   920         if (r.getMessage() == null || (wsdlPort != null && getMessage().isOneWay(wsdlPort))) {
   921             return r;
   922         }
   924         // otherwise populate WS-Addressing headers
   925         populateAddressingHeaders(binding, r, wsdlPort, seiModel);
   926         return r;
   927     }
   929     /**
   930      * Creates a server-side response {@link Packet} from a request
   931      * packet ({@code this}). If WS-Addressing is enabled, <code>action</code>
   932      * is used as Action Message Addressing Property.
   933      * <p><p>
   934      * This method should be called only for creating protocol response messages
   935      * that require a particular value of Action since they are not associated
   936      * with a {@link WSBinding} and {@link WSDLPort} but do know the {@link AddressingVersion}
   937      * and {@link SOAPVersion}.
   938      *
   939      * @param responseMessage The {@link Message} that represents a reply. Can be null.
   940      * @param addressingVersion The WS-Addressing version of the response message.
   941      * @param soapVersion The SOAP version of the response message.
   942      * @param action The response Action Message Addressing Property value.
   943      * @return response packet
   944      */
   945     public Packet createServerResponse(@Nullable Message responseMessage, @NotNull AddressingVersion addressingVersion, @NotNull SOAPVersion soapVersion, @NotNull String action) {
   946         Packet responsePacket = createClientResponse(responseMessage);
   947         responsePacket.setState(State.ServerResponse);
   948         // populate WS-A headers only if WS-A is enabled
   949         if (addressingVersion == null) {
   950             return responsePacket;
   951         }
   952         //populate WS-A headers only if the request has addressing headers
   953         String inputAction = AddressingUtils.getAction(this.getMessage().getHeaders(), addressingVersion, soapVersion);
   954         if (inputAction == null) {
   955             return responsePacket;
   956         }
   958         populateAddressingHeaders(responsePacket, addressingVersion, soapVersion, action, false);
   959         return responsePacket;
   960     }
   962     /**
   963      * Overwrites the {@link Message} of the response packet ({@code this}) by the given {@link Message}.
   964      * Unlike {@link #setMessage(Message)}, fill in the addressing headers correctly, and this process
   965      * requires the access to the request packet.
   966      *
   967      * <p>
   968      * This method is useful when the caller needs to swap a response message completely to a new one.
   969      *
   970      * @see #createServerResponse(Message, AddressingVersion, SOAPVersion, String)
   971      */
   972     public void setResponseMessage(@NotNull Packet request, @Nullable Message responseMessage, @NotNull AddressingVersion addressingVersion, @NotNull SOAPVersion soapVersion, @NotNull String action) {
   973         Packet temp = request.createServerResponse(responseMessage, addressingVersion, soapVersion, action);
   974         setMessage(temp.getMessage());
   975     }
   977     private void populateAddressingHeaders(Packet responsePacket, AddressingVersion av, SOAPVersion sv, String action, boolean mustUnderstand) {
   978         // populate WS-A headers only if WS-A is enabled
   979         if (av == null) return;
   981         // if one-way, then dont populate any WS-A headers
   982         if (responsePacket.getMessage() == null)
   983             return;
   985         MessageHeaders hl = responsePacket.getMessage().getHeaders();
   987         WsaPropertyBag wpb = getSatellite(WsaPropertyBag.class);
   988         Message msg = getMessage();
   989         // wsa:To
   990         WSEndpointReference replyTo = null;
   991         Header replyToFromRequestMsg = AddressingUtils.getFirstHeader(msg.getHeaders(), av.replyToTag, true, sv);
   992         Header replyToFromResponseMsg = hl.get(av.toTag, false);
   993         boolean replaceToTag = true;
   994         try{
   995             if (replyToFromRequestMsg != null){
   996                 replyTo = replyToFromRequestMsg.readAsEPR(av);
   997             }
   998             if (replyToFromResponseMsg != null && replyTo == null) {
   999                 replaceToTag = false;
  1001         } catch (XMLStreamException e) {
  1002             throw new WebServiceException(AddressingMessages.REPLY_TO_CANNOT_PARSE(), e);
  1004         if (replyTo == null) {
  1005               replyTo = AddressingUtils.getReplyTo(msg.getHeaders(), av, sv);
  1008         // wsa:Action, add if the message doesn't already contain it,
  1009         // generally true for SEI case where there is SEIModel or WSDLModel
  1010         //           false for Provider with no wsdl, Expects User to set the coresponding header on the Message.
  1011         if (AddressingUtils.getAction(responsePacket.getMessage().getHeaders(), av, sv) == null) {
  1012             //wsa:Action header is not set in the message, so use the wsa:Action  passed as the parameter.
  1013             hl.add(new StringHeader(av.actionTag, action, sv, mustUnderstand));
  1016         // wsa:MessageID
  1017         if (responsePacket.getMessage().getHeaders().get(av.messageIDTag, false) == null) {
  1018             // if header doesn't exist, method getID creates a new random id
  1019             String newID = Message.generateMessageID();
  1020             hl.add(new StringHeader(av.messageIDTag, newID));
  1023         // wsa:RelatesTo
  1024         String mid = null;
  1025         if (wpb != null) {
  1026             mid = wpb.getMessageID();
  1028         if (mid == null) {
  1029             mid = AddressingUtils.getMessageID(msg.getHeaders(), av, sv);
  1031         if (mid != null) {
  1032             hl.addOrReplace(new RelatesToHeader(av.relatesToTag, mid));
  1036         // populate reference parameters
  1037         WSEndpointReference refpEPR = null;
  1038         if (responsePacket.getMessage().isFault()) {
  1039             // choose FaultTo
  1040             if (wpb != null) {
  1041                 refpEPR = wpb.getFaultToFromRequest();
  1043             if (refpEPR == null) {
  1044                 refpEPR = AddressingUtils.getFaultTo(msg.getHeaders(), av, sv);
  1046             // if FaultTo is null, then use ReplyTo
  1047             if (refpEPR == null) {
  1048                 refpEPR = replyTo;
  1050         } else {
  1051             // choose ReplyTo
  1052             refpEPR = replyTo;
  1054         if (replaceToTag && refpEPR != null) {
  1055             hl.addOrReplace(new StringHeader(av.toTag, refpEPR.getAddress()));
  1056             refpEPR.addReferenceParametersToList(hl);
  1060     private void populateAddressingHeaders(WSBinding binding, Packet responsePacket, WSDLPort wsdlPort, SEIModel seiModel) {
  1061         AddressingVersion addressingVersion = binding.getAddressingVersion();
  1063         if (addressingVersion == null) {
  1064             return;
  1067         WsaTubeHelper wsaHelper = addressingVersion.getWsaHelper(wsdlPort, seiModel, binding);
  1068         String action = responsePacket.getMessage().isFault() ?
  1069                 wsaHelper.getFaultAction(this, responsePacket) :
  1070                 wsaHelper.getOutputAction(this);
  1071         if (action == null) {
  1072             LOGGER.info("WSA headers are not added as value for wsa:Action cannot be resolved for this message");
  1073             return;
  1075         populateAddressingHeaders(responsePacket, addressingVersion, binding.getSOAPVersion(), action, AddressingVersion.isRequired(binding));
  1078     public String toShortString() {
  1079       return super.toString();
  1082     // For use only in a debugger
  1083     @Override
  1084     public String toString() {
  1085       StringBuilder buf = new StringBuilder();
  1086       buf.append(super.toString());
  1087       String content;
  1088         try {
  1089             Message msg = getMessage();
  1090         if (msg != null) {
  1091                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
  1092                         XMLStreamWriter xmlWriter = XMLStreamWriterFactory.create(baos, "UTF-8");
  1093                         msg.copy().writeTo(xmlWriter);
  1094                         xmlWriter.flush();
  1095                         xmlWriter.close();
  1096                         baos.flush();
  1097                         XMLStreamWriterFactory.recycle(xmlWriter);
  1099                         byte[] bytes = baos.toByteArray();
  1100                         //message = Messages.create(XMLStreamReaderFactory.create(null, new ByteArrayInputStream(bytes), "UTF-8", true));
  1101                         content = new String(bytes, "UTF-8");
  1102                 } else {
  1103                     content = "<none>";
  1105         } catch (Throwable t) {
  1106                 throw new WebServiceException(t);
  1108       buf.append(" Content: ").append(content);
  1109       return buf.toString();
  1112     // completes TypedMap
  1113     private static final PropertyMap model;
  1115     static {
  1116         model = parse(Packet.class);
  1119     @Override
  1120     protected PropertyMap getPropertyMap() {
  1121         return model;
  1124     public Map<String, Object> asMapIncludingInvocationProperties() {
  1125         final Map<String, Object> asMap = asMap();
  1126         return new AbstractMap<String, Object>() {
  1127             @Override
  1128             public Object get(Object key) {
  1129                 Object o = asMap.get(key);
  1130                 if (o != null)
  1131                     return o;
  1133                 return invocationProperties.get(key);
  1136             @Override
  1137             public int size() {
  1138                 return asMap.size() + invocationProperties.size();
  1141             @Override
  1142             public boolean containsKey(Object key) {
  1143                 if (asMap.containsKey(key))
  1144                     return true;
  1145                 return invocationProperties.containsKey(key);
  1148             @Override
  1149             public Set<Entry<String, Object>> entrySet() {
  1150                 final Set<Entry<String, Object>> asMapEntries = asMap.entrySet();
  1151                 final Set<Entry<String, Object>> ipEntries = invocationProperties.entrySet();
  1153                 return new AbstractSet<Entry<String, Object>>() {
  1154                     @Override
  1155                     public Iterator<Entry<String, Object>> iterator() {
  1156                         final Iterator<Entry<String, Object>> asMapIt = asMapEntries.iterator();
  1157                         final Iterator<Entry<String, Object>> ipIt = ipEntries.iterator();
  1159                         return new Iterator<Entry<String, Object>>() {
  1160                             @Override
  1161                             public boolean hasNext() {
  1162                                 return asMapIt.hasNext() || ipIt.hasNext();
  1165                             @Override
  1166                             public java.util.Map.Entry<String, Object> next() {
  1167                                 if (asMapIt.hasNext())
  1168                                     return asMapIt.next();
  1169                                 return ipIt.next();
  1172                             @Override
  1173                             public void remove() {
  1174                                 throw new UnsupportedOperationException();
  1176                         };
  1179                     @Override
  1180                     public int size() {
  1181                         return asMap.size() + invocationProperties.size();
  1183                 };
  1186             @Override
  1187             public Object put(String key, Object value) {
  1188                 if (supports(key))
  1189                     return asMap.put(key, value);
  1191                 return invocationProperties.put(key, value);
  1194             @Override
  1195             public void clear() {
  1196                 asMap.clear();
  1197                 invocationProperties.clear();
  1200             @Override
  1201             public Object remove(Object key) {
  1202                 if (supports(key))
  1203                     return asMap.remove(key);
  1205                 return invocationProperties.remove(key);
  1207         };
  1210     private static final Logger LOGGER = Logger.getLogger(Packet.class.getName());
  1212     @Override
  1213     public SOAPMessage getSOAPMessage() throws SOAPException {
  1214         return getAsSOAPMessage();
  1217     //TODO replace the message to a SAAJMEssage issue - JRFSAAJMessage or SAAJMessage?
  1218     @Override
  1219     public SOAPMessage getAsSOAPMessage() throws SOAPException {
  1220         Message msg = this.getMessage();
  1221         if (msg == null)
  1222             return null;
  1223         if (msg instanceof MessageWritable)
  1224             ((MessageWritable) msg).setMTOMConfiguration(mtomFeature);
  1225         return msg.readAsSOAPMessage(this, this.getState().isInbound());
  1228     public
  1229     Codec codec = null;
  1230     public Codec getCodec() {
  1231         if (codec != null) {
  1232             return codec;
  1234         if (endpoint != null) {
  1235             codec = endpoint.createCodec();
  1237         WSBinding wsb = getBinding();
  1238         if (wsb != null) {
  1239             codec = wsb.getBindingId().createEncoder(wsb);
  1241         return codec;
  1244     @Override
  1245     public com.oracle.webservices.internal.api.message.ContentType writeTo( OutputStream out ) throws IOException {
  1246         Message msg = getInternalMessage();
  1247         if (msg instanceof MessageWritable) {
  1248             ((MessageWritable) msg).setMTOMConfiguration(mtomFeature);
  1249             return ((MessageWritable)msg).writeTo(out);
  1251         return getCodec().encode(this, out);
  1254     public com.oracle.webservices.internal.api.message.ContentType writeTo( WritableByteChannel buffer ) {
  1255         return getCodec().encode(this, buffer);
  1258     private ContentType contentType;
  1260     /**
  1261      * If the request's Content-Type is multipart/related; type=application/xop+xml, then this set to to true
  1263      * Used on server-side, for encoding the repsonse.
  1264      */
  1265     private Boolean mtomRequest;
  1267     /**
  1268      * Based on request's Accept header this is set.
  1269      * Currently only set if MTOMFeature is enabled.
  1271      * Should be used on server-side, for encoding the response.
  1272      */
  1273     private Boolean mtomAcceptable;
  1275     private MTOMFeature mtomFeature;
  1277     public Boolean getMtomRequest() {
  1278         return mtomRequest;
  1281     public void setMtomRequest(Boolean mtomRequest) {
  1282         this.mtomRequest = mtomRequest;
  1285     public Boolean getMtomAcceptable() {
  1286         return mtomAcceptable;
  1289     Boolean checkMtomAcceptable;
  1290     public void checkMtomAcceptable() {
  1291         if (checkMtomAcceptable == null) {
  1292             if (acceptableMimeTypes == null || isFastInfosetDisabled) {
  1293                 checkMtomAcceptable = false;
  1294             } else {
  1295                 checkMtomAcceptable = (acceptableMimeTypes.indexOf(MtomCodec.XOP_XML_MIME_TYPE) != -1);
  1296 //                StringTokenizer st = new StringTokenizer(acceptableMimeTypes, ",");
  1297 //                while (st.hasMoreTokens()) {
  1298 //                    final String token = st.nextToken().trim();
  1299 //                    if (token.toLowerCase().contains(MtomCodec.XOP_XML_MIME_TYPE)) {
  1300 //                        mtomAcceptable = true;
  1301 //                    }
  1302 //                }
  1303 //                if (mtomAcceptable == null) mtomAcceptable = false;
  1306         mtomAcceptable = checkMtomAcceptable;
  1309     private Boolean fastInfosetAcceptable;
  1311     public Boolean getFastInfosetAcceptable(String fiMimeType) {
  1312         if (fastInfosetAcceptable == null) {
  1313             if (acceptableMimeTypes == null || isFastInfosetDisabled) {
  1314                 fastInfosetAcceptable = false;
  1315             } else {
  1316                 fastInfosetAcceptable = (acceptableMimeTypes.indexOf(fiMimeType) != -1);
  1318 //        if (accept == null || isFastInfosetDisabled) return false;
  1319 //
  1320 //        StringTokenizer st = new StringTokenizer(accept, ",");
  1321 //        while (st.hasMoreTokens()) {
  1322 //            final String token = st.nextToken().trim();
  1323 //            if (token.equalsIgnoreCase(fiMimeType)) {
  1324 //                return true;
  1325 //            }
  1326 //        }
  1327 //        return false;
  1329         return fastInfosetAcceptable;
  1333     public void setMtomFeature(MTOMFeature mtomFeature) {
  1334         this.mtomFeature = mtomFeature;
  1337     public MTOMFeature getMtomFeature() {
  1338         //If we have a binding, use that in preference to an explicitly
  1339         //set MTOMFeature
  1340         WSBinding binding = getBinding();
  1341         if (binding != null) {
  1342             return binding.getFeature(MTOMFeature.class);
  1344         return mtomFeature;
  1347     @Override
  1348     public com.oracle.webservices.internal.api.message.ContentType getContentType() {
  1349         if (contentType == null) {
  1350             contentType = getInternalContentType();
  1352         if (contentType == null) {
  1353             contentType = getCodec().getStaticContentType(this);
  1355         if (contentType == null) {
  1356             //TODO write to buffer
  1358         return contentType;
  1361     public ContentType getInternalContentType() {
  1362         Message msg = getInternalMessage();
  1363         if (msg instanceof MessageWritable) {
  1364             return ((MessageWritable)msg).getContentType();
  1366         return contentType;
  1369     public void setContentType(ContentType contentType) {
  1370         this.contentType = contentType;
  1373     public enum Status {
  1374         Request, Response, Unknown;
  1375         public boolean isRequest()  { return Request.equals(this); }
  1376         public boolean isResponse() { return Response.equals(this); }
  1379     public enum State {
  1380         ServerRequest(true), ClientRequest(false), ServerResponse(false), ClientResponse(true);
  1381         private boolean inbound;
  1382         State(boolean inbound) {
  1383             this.inbound = inbound;
  1385         public boolean isInbound() {
  1386             return inbound;
  1390 //    private Status status = Status.Unknown;
  1392     //Default state is ServerRequest - some custom adapters may not set the value of state
  1393     //upon server request - all other code paths should set it
  1394     private State state = State.ServerRequest;
  1396 //    public Status getStatus() { return status; }
  1398     public State getState() { return state; }
  1399     public void setState(State state) { this.state = state; }
  1401     public boolean shouldUseMtom() {
  1402         if (getState().isInbound()) {
  1403             return isMtomContentType();
  1404         } else {
  1405             return shouldUseMtomOutbound();
  1409     private boolean shouldUseMtomOutbound() {
  1410         //Use the getter to make sure all the logic is executed correctly
  1411         MTOMFeature myMtomFeature = getMtomFeature();
  1412         if(myMtomFeature != null && myMtomFeature.isEnabled()) {
  1413             //On client, always use XOP encoding if MTOM is enabled
  1414             //On Server, mtomAcceptable and mtomRequest will be set - use XOP encoding
  1415             //if either request is XOP encoded (mtomRequest) or
  1416             //client accepts XOP encoding (mtomAcceptable)
  1417             if (getMtomAcceptable() == null && getMtomRequest() == null) {
  1418                 return true;
  1419             } else {
  1420                 if (getMtomAcceptable() != null &&  getMtomAcceptable() && getState().equals(State.ServerResponse)) {
  1421                     return true;
  1423                 if (getMtomRequest() != null && getMtomRequest() && getState().equals(State.ServerResponse)) {
  1424                     return true;
  1426                 if (getMtomRequest() != null && getMtomRequest() && getState().equals(State.ClientRequest)) {
  1427                     return true;
  1431         return false;
  1434     private boolean isMtomContentType() {
  1435         return (getInternalContentType() != null) &&
  1436         (getInternalContentType().getContentType().contains("application/xop+xml"));
  1439     /**
  1440      * @deprecated
  1441      */
  1442     public void addSatellite(@NotNull com.sun.xml.internal.ws.api.PropertySet satellite) {
  1443         super.addSatellite(satellite);
  1446     /**
  1447      * @deprecated
  1448      */
  1449     public void addSatellite(@NotNull Class keyClass, @NotNull com.sun.xml.internal.ws.api.PropertySet satellite) {
  1450         super.addSatellite(keyClass, satellite);
  1453     /**
  1454      * @deprecated
  1455      */
  1456     public void copySatelliteInto(@NotNull com.sun.xml.internal.ws.api.DistributedPropertySet r) {
  1457         super.copySatelliteInto(r);
  1460     /**
  1461      * @deprecated
  1462      */
  1463     public void removeSatellite(com.sun.xml.internal.ws.api.PropertySet satellite) {
  1464         super.removeSatellite(satellite);
  1467     /**
  1468      * This is propogated from SOAPBindingCodec and will affect isMtomAcceptable and isFastInfosetAcceptable
  1469      */
  1470     private boolean isFastInfosetDisabled;
  1472     public void setFastInfosetDisabled(boolean b) {
  1473         isFastInfosetDisabled = b;

mercurial