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

Print this page


   1 /*
   2  * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.ws.api.message;
  27 


  28 import com.sun.istack.internal.NotNull;
  29 import com.sun.istack.internal.Nullable;
  30 import com.sun.xml.internal.bind.marshaller.SAX2DOMEx;
  31 import com.sun.xml.internal.ws.addressing.WsaPropertyBag;

  32 import com.sun.xml.internal.ws.addressing.WsaTubeHelper;
  33 import com.sun.xml.internal.ws.addressing.model.InvalidAddressingHeaderException;
  34 import com.sun.xml.internal.ws.api.*;


  35 import com.sun.xml.internal.ws.api.addressing.AddressingVersion;
  36 import com.sun.xml.internal.ws.api.addressing.WSEndpointReference;
  37 import com.sun.xml.internal.ws.api.message.saaj.SAAJFactory;
  38 import com.sun.xml.internal.ws.api.model.JavaMethod;
  39 import com.sun.xml.internal.ws.api.model.SEIModel;

  40 import com.sun.xml.internal.ws.api.model.wsdl.WSDLOperation;
  41 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
  42 import com.sun.xml.internal.ws.api.pipe.Codec;
  43 import com.sun.xml.internal.ws.api.pipe.Tube;
  44 import com.sun.xml.internal.ws.api.server.Adapter;
  45 import com.sun.xml.internal.ws.api.server.TransportBackChannel;
  46 import com.sun.xml.internal.ws.api.server.WSEndpoint;
  47 import com.sun.xml.internal.ws.api.server.WebServiceContextDelegate;
  48 import com.sun.xml.internal.ws.api.streaming.XMLStreamWriterFactory;
  49 import com.sun.xml.internal.ws.client.*;
  50 import com.sun.xml.internal.ws.developer.JAXWSProperties;

  51 import com.sun.xml.internal.ws.message.RelatesToHeader;
  52 import com.sun.xml.internal.ws.message.StringHeader;
  53 import com.sun.xml.internal.ws.transport.http.WSHTTPConnection;
  54 import com.sun.xml.internal.ws.message.saaj.SAAJMessage;
  55 import com.sun.xml.internal.ws.server.WSEndpointImpl;
  56 import com.sun.xml.internal.ws.util.DOMUtil;
  57 import com.sun.xml.internal.ws.util.xml.XmlUtil;
  58 import com.sun.xml.internal.ws.wsdl.DispatchException;
  59 import com.sun.xml.internal.ws.wsdl.OperationDispatcher;


  60 
  61 import com.sun.xml.internal.org.jvnet.ws.message.ContentType;
  62 import org.w3c.dom.Document;
  63 import org.w3c.dom.Element;
  64 import org.xml.sax.SAXException;
  65 
  66 import javax.xml.namespace.QName;
  67 import javax.xml.soap.SOAPException;
  68 import javax.xml.soap.SOAPMessage;
  69 import javax.xml.stream.XMLStreamWriter;

  70 import javax.xml.ws.BindingProvider;
  71 import javax.xml.ws.Dispatch;
  72 import javax.xml.ws.WebServiceContext;
  73 import javax.xml.ws.WebServiceException;
  74 import javax.xml.ws.handler.LogicalMessageContext;
  75 import javax.xml.ws.handler.MessageContext;
  76 import javax.xml.ws.handler.soap.SOAPMessageContext;


  77 import java.util.*;
  78 import java.util.logging.Logger;
  79 import java.io.ByteArrayOutputStream;
  80 import java.io.IOException;
  81 import java.io.OutputStream;
  82 import java.nio.ByteBuffer;
  83 import java.nio.channels.WritableByteChannel;
  84 
  85 /**
  86  * Represents a container of a {@link Message}.
  87  *
  88  * <h2>What is a {@link Packet}?</h2>
  89  * <p>
  90  * A packet can be thought of as a frame/envelope/package that wraps
  91  * a {@link Message}. A packet keeps track of optional metadata (properties)
  92  * about a {@link Message} that doesn't go across the wire.
  93  * This roughly corresponds to {@link MessageContext} in the JAX-WS API.
  94  *
  95  * <p>
  96  * Usually a packet contains a {@link Message} in it, but sometimes
  97  * (such as for a reply of an one-way operation), a packet may
  98  * float around without a {@link Message} in it.
  99  *
 100  *
 101  * <a name="properties"></a>
 102  * <h2>Properties</h2>


 125  * {@link BindingProvider#getRequestContext() Request context} is used to
 126  * seed the initial values of {@link Packet}.
 127  * Some of those values go to strongly-typed fields, and others go to
 128  * {@link #invocationProperties}, as they need to be retained in the reply message.
 129  *
 130  * <p>
 131  * Similarly, {@link BindingProvider#getResponseContext() response context}
 132  * is constructed from {@link Packet} (or rather it's just a view of {@link Packet}.)
 133  * by using properties from {@link #invocationProperties},
 134  * modulo properties named explicitly in {@link #getHandlerScopePropertyNames(boolean)}.
 135  * IOW, properties added to {@link #invocationProperties}
 136  * are exposed to the response context by default.
 137  *
 138  *
 139  *
 140  * <h3>TODO</h3>
 141  * <ol>
 142  *  <li>this class needs to be cloneable since Message is copiable.
 143  *  <li>The three live views aren't implemented correctly. It will be
 144  *      more work to do so, although I'm sure it's possible.
 145  *  <li>{@link Property} annotation is to make it easy
 146  *      for {@link MessageContext} to export properties on this object,
 147  *      but it probably needs some clean up.
 148  * </ol>
 149  *
 150  * @author Kohsuke Kawaguchi
 151  */
 152 public final class Packet
 153     extends DistributedPropertySet
 154     implements com.sun.xml.internal.org.jvnet.ws.message.MessageContext
 155 {

 156 
 157     /**
 158      * Creates a {@link Packet} that wraps a given {@link Message}.
 159      *
 160      * <p>
 161      * This method should be only used to create a fresh {@link Packet}.
 162      * To create a {@link Packet} for a reply, use {@link #createResponse(Message)}.
 163      *
 164      * @param request
 165      *      The request {@link Message}. Can be null.
 166      */
 167     public Packet(Message request) {
 168         this();
 169         this.message = request;

 170     }
 171 
 172     /**
 173      * Creates an empty {@link Packet} that doesn't have any {@link Message}.
 174      */
 175     public Packet() {
 176         this.invocationProperties = new HashMap<String, Object>();
 177     }
 178 
 179     /**
 180      * Used by {@link #createResponse(Message)} and {@link #copy(boolean)}.
 181      */
 182     private Packet(Packet that) {
 183         that.copySatelliteInto((DistributedPropertySet) this);
 184         this.handlerConfig = that.handlerConfig;
 185         this.invocationProperties = that.invocationProperties;
 186         this.handlerScopePropertyNames = that.handlerScopePropertyNames;
 187         this.contentNegotiation = that.contentNegotiation;
 188         this.wasTransportSecure = that.wasTransportSecure;
 189         this.transportBackChannel = that.transportBackChannel;
 190         this.endpointAddress = that.endpointAddress;
 191         this.isAdapterDeliversNonAnonymousResponse = that.isAdapterDeliversNonAnonymousResponse;
 192         this.wsdlOperation = that.wsdlOperation;
 193         this.acceptableMimeTypes = that.acceptableMimeTypes;
 194         this.endpoint = that.endpoint;
 195         this.proxy = that.proxy;
 196         this.webServiceContextDelegate = that.webServiceContextDelegate;
 197         this.soapAction = that.soapAction;
 198         this.expectReply = that.expectReply;
 199         this.component = that.component;
 200         // copy other properties that need to be copied. is there any?
 201     }
 202 
 203     /**
 204      * Creates a copy of this {@link Packet}.
 205      *
 206      * @param copyMessage determines whether the {@link Message} from the original {@link Packet} should be copied as
 207      *        well, or not. If the value is {@code false}, the {@link Message} in the copy of the {@link Packet} is {@code null}.
 208      * @return copy of the original packet
 209      */
 210     public Packet copy(boolean copyMessage) {
 211         // the copy constructor is originally designed for creating a response packet,
 212         // but so far the implementation is usable for this purpose as well, so calling the copy constructor
 213         // to avoid code dupliation.
 214         Packet copy = new Packet(this);
 215         if (copyMessage && this.message != null) {
 216             copy.message = this.message.copy();
 217         }
 218 
 219         return copy;
 220     }
 221 
 222     private Message message;
 223 
 224     /**
 225      * Gets the last {@link Message} set through {@link #setMessage(Message)}.
 226      *
 227      * @return may null. See the class javadoc for when it's null.
 228      */
 229     public Message getMessage() {



 230         return message;
 231     }
 232 




 233     public WSBinding getBinding() {
 234         if (endpoint != null)
 235                 return endpoint.getBinding();
 236         if (proxy != null)

 237                 return (WSBinding) proxy.getBinding();

 238         return null;
 239     }
 240     /**
 241      * Sets a {@link Message} to this packet.
 242      *
 243      * @param message Can be null.
 244      */
 245     public void setMessage(Message message) {
 246         this.message = message;

 247     }
 248 


 249     private QName wsdlOperation;
 250 
 251     /**
 252      * Returns the QName of the wsdl operation associated with this packet.
 253      * <p/>
 254      * Information such as Payload QName, wsa:Action header, SOAPAction HTTP header are used depending on the features
 255      * enabled on the particular port.
 256      *
 257      * @return null if there is no WSDL model or
 258      *         runtime cannot uniquely identify the wsdl operation from the information in the packet.
 259      */
 260     @com.sun.xml.internal.ws.api.PropertySet.Property(MessageContext.WSDL_OPERATION)
 261     public final
 262     @Nullable
 263     QName getWSDLOperation() {
 264         if (wsdlOperation != null)


 265             return wsdlOperation;

 266 


 267         OperationDispatcher opDispatcher = null;
 268         if (endpoint != null) {
 269             opDispatcher = ((WSEndpointImpl) endpoint).getOperationDispatcher();
 270         } else if (proxy != null) {
 271             opDispatcher = ((Stub) proxy).getOperationDispatcher();
 272         }
 273         //OpDispatcher is null when there is no WSDLModel
 274         if (opDispatcher != null) {
 275             try {
 276                 wsdlOperation = opDispatcher.getWSDLOperationQName(this);
 277             } catch (DispatchException e) {
 278                 //Ignore, this might be a protocol message which may not have a wsdl operation
 279                 //LOGGER.info("Cannot resolve wsdl operation that this Packet is targeted for.");
 280             }
 281         }
 282         return wsdlOperation;
 283     }
 284 
 285     /**
 286      * Set the wsdl operation to avoid lookup from other data.
 287      * This is useful in SEI based clients, where the WSDL operation can be known
 288      * from the associated {@link JavaMethod}
 289      *
 290      * @param wsdlOp QName
 291      */
 292     public void setWSDLOperation(QName wsdlOp) {
 293         this.wsdlOperation = wsdlOp;
 294     }
 295 
 296     /**
 297      * True if this message came from a transport (IOW inbound),
 298      * and in paricular from a "secure" transport. A transport
 299      * needs to set this flag appropriately.
 300      *
 301      * <p>
 302      * This is a requirement from the security team.


 316      * Outbound transport headers are captured in a transport neutral way.
 317      *
 318      * <p>
 319      * Transports may choose to ignore certain headers that interfere with
 320      * its correct operation, such as
 321      * <tt>Content-Type</tt> and <tt>Content-Length</tt>.
 322      */
 323     public static final String OUTBOUND_TRANSPORT_HEADERS = "com.sun.xml.internal.ws.api.message.packet.outbound.transport.headers";
 324 
 325     /**
 326      *
 327      */
 328     public static final String HA_INFO = "com.sun.xml.internal.ws.api.message.packet.hainfo";
 329 
 330 
 331     /**
 332      * This property holds the snapshot of HandlerConfiguration
 333      * at the time of invocation.
 334      * This property is used by MUPipe and HandlerPipe implementations.
 335      */
 336     @com.sun.xml.internal.ws.api.PropertySet.Property(BindingProviderProperties.JAXWS_HANDLER_CONFIG)
 337     public HandlerConfiguration handlerConfig;
 338 
 339     /**
 340      * If a message originates from a proxy stub that implements
 341      * a port interface, this field is set to point to that object.
 342      *
 343      * TODO: who's using this property?
 344      */
 345     @com.sun.xml.internal.ws.api.PropertySet.Property(BindingProviderProperties.JAXWS_CLIENT_HANDLE_PROPERTY)
 346     public BindingProvider proxy;
 347 
 348     /**
 349      * Determines if the governing {@link Adapter} or {@link Fiber.CompletionCallback} will handle delivering
 350      * response messages targeted at non-anonymous endpoint addresses.  Prior to the introduction of this
 351      * flag the {@link WsaServerTube} would deliver non-anonymous responses.

 352      */
 353     public boolean isAdapterDeliversNonAnonymousResponse;
 354 
 355     /**











 356      * The endpoint address to which this message is sent to.
 357      *
 358      * <p>
 359      * The JAX-WS spec allows this to be changed for each message,
 360      * so it's designed to be a property.
 361      *
 362      * <p>
 363      * Must not be null for a request message on the client. Otherwise
 364      * it's null.
 365      */
 366     public EndpointAddress endpointAddress;
 367 
 368     /**
 369      * @deprecated
 370      *      The programatic acccess should be done via
 371      *      {@link #endpointAddress}. This is for JAX-WS client applications
 372      *      that access this property via {@link BindingProvider#ENDPOINT_ADDRESS_PROPERTY}.
 373      */
 374     @com.sun.xml.internal.ws.api.PropertySet.Property(BindingProvider.ENDPOINT_ADDRESS_PROPERTY)
 375     public String getEndPointAddressString() {
 376         if (endpointAddress == null)
 377             return null;
 378         else
 379             return endpointAddress.toString();
 380     }

 381 
 382     public void setEndPointAddressString(String s) {
 383         if (s == null)
 384             this.endpointAddress = null;
 385         else
 386             this.endpointAddress = EndpointAddress.create(s);
 387     }

 388 
 389     /**
 390      * The value of {@link ContentNegotiation#PROPERTY}
 391      * property.
 392      * <p/>
 393      * This property is used only on the client side.
 394      */
 395     public ContentNegotiation contentNegotiation;
 396 
 397     @com.sun.xml.internal.ws.api.PropertySet.Property(ContentNegotiation.PROPERTY)
 398     public String getContentNegotiationString() {
 399         return (contentNegotiation != null) ? contentNegotiation.toString() : null;
 400     }
 401 
 402     public void setContentNegotiationString(String s) {
 403         if (s == null)
 404             contentNegotiation = null;
 405         else {
 406             try {
 407                 contentNegotiation = ContentNegotiation.valueOf(s);
 408             } catch (IllegalArgumentException e) {
 409                 // If the value is not recognized default to none
 410                 contentNegotiation = ContentNegotiation.none;
 411             }
 412         }
 413     }
 414 
 415     /**
 416      * Gives a list of Reference Parameters in the Message
 417      * <p>
 418      * Headers which have attribute wsa:IsReferenceParameter="true"
 419      * This is not cached as one may reset the Message.
 420      *<p>
 421      */
 422     @com.sun.xml.internal.ws.api.PropertySet.Property(MessageContext.REFERENCE_PARAMETERS)
 423     public
 424     @NotNull
 425     List<Element> getReferenceParameters() {

 426         List<Element> refParams = new ArrayList<Element>();
 427         if (message == null) {
 428             return refParams;
 429         }
 430         HeaderList hl = message.getHeaders();
 431         for (Header h : hl) {
 432             String attr = h.getAttribute(AddressingVersion.W3C.nsUri, "IsReferenceParameter");
 433             if (attr != null && (attr.equals("true") || attr.equals("1"))) {
 434                 Document d = DOMUtil.createDom();
 435                 SAX2DOMEx s2d = new SAX2DOMEx(d);
 436                 try {
 437                     h.writeTo(s2d, XmlUtil.DRACONIAN_ERROR_HANDLER);
 438                     refParams.add((Element) d.getLastChild());
 439                 } catch (SAXException e) {
 440                     throw new WebServiceException(e);
 441                 }
 442                 /*
 443                 DOMResult result = new DOMResult(d);
 444                 XMLDOMWriterImpl domwriter = new XMLDOMWriterImpl(result);
 445                 try {
 446                     h.writeTo(domwriter);
 447                     refParams.add((Element) result.getNode().getLastChild());
 448                 } catch (XMLStreamException e) {
 449                     throw new WebServiceException(e);
 450                 }
 451                 */
 452             }
 453         }
 454         return refParams;
 455     }
 456 
 457     /**
 458      * @deprecated
 459      *      This method is for exposing header list through {@link PropertySet#get(Object)},
 460      *      for user applications, and should never be invoked directly from within the JAX-WS RI.
 461      */
 462     @com.sun.xml.internal.ws.api.PropertySet.Property(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY)
 463     /*package*/ HeaderList getHeaderList() {
 464         if (message == null) return null;
 465         return message.getHeaders();



 466     }
 467 
 468     /**
 469      * The list of MIME types that are acceptable to a receiver
 470      * of an outbound message.
 471      *
 472      * This property is used only on the server side.
 473      *
 474      * <p>The representation shall be that specified by the HTTP Accept
 475      * request-header field.
 476      *
 477      * <p>The list of content types will be obtained from the transport
 478      * meta-data of a inbound message in a request/response message exchange.
 479      * Hence this property will be set by the service-side transport pipe.
 480      */
 481     public String acceptableMimeTypes;
 482 
 483     /**
 484      * When non-null, this object is consulted to
 485      * implement {@link WebServiceContext} methods


 517      *      The previous value of {@link #transportBackChannel}.
 518      */
 519     public TransportBackChannel keepTransportBackChannelOpen() {
 520         TransportBackChannel r = transportBackChannel;
 521         transportBackChannel = null;
 522         return r;
 523     }
 524 
 525     /**
 526       * The governing owner of this packet.  On the service-side this is the {@link Adapter} and on the client it is the {@link Stub}.
 527       *
 528       */
 529      public Component component;
 530 
 531     /**
 532      * The governing {@link WSEndpoint} in which this message is floating.
 533      *
 534      * <p>
 535      * This property is set if and only if this is on the server side.
 536      */
 537     @com.sun.xml.internal.ws.api.PropertySet.Property(JAXWSProperties.WSENDPOINT)
 538     public WSEndpoint endpoint;
 539 
 540     /**
 541      * The value of the SOAPAction header associated with the message.
 542      *
 543      * <p>
 544      * For outgoing messages, the transport may sends out this value.
 545      * If this field is null, the transport may choose to send <tt>""</tt>
 546      * (quoted empty string.)
 547      *
 548      * For incoming messages, the transport will set this field.
 549      * If the incoming message did not contain the SOAPAction header,
 550      * the transport sets this field to null.
 551      *
 552      * <p>
 553      * If the value is non-null, it must be always in the quoted form.
 554      * The value can be null.
 555      *
 556      * <p>
 557      * Note that the way the transport sends this value out depends on
 558      * transport and SOAP version.
 559      * <p/>
 560      * For HTTP transport and SOAP 1.1, BP requires that SOAPAction
 561      * header is present (See {@BP R2744} and {@BP R2745}.) For SOAP 1.2,
 562      * this is moved to the parameter of the "application/soap+xml".
 563      */
 564     @com.sun.xml.internal.ws.api.PropertySet.Property(BindingProvider.SOAPACTION_URI_PROPERTY)
 565     public String soapAction;
 566 
 567     /**
 568      * A hint indicating that whether a transport should expect
 569      * a reply back from the server.
 570      *
 571      * <p>
 572      * This property is used on the client-side for
 573      * outbound messages, so that a pipeline
 574      * can communicate to the terminal (or intermediate) {@link Tube}s
 575      * about this knowledge.
 576      *
 577      * <p>
 578      * This property <b>MUST NOT</b> be used by 2-way transports
 579      * that have the transport back channel. Those transports
 580      * must always check a reply coming through the transport back
 581      * channel regardless of this value, and act accordingly.
 582      * (This is because the expectation of the client and
 583      * that of the server can be different, for example because
 584      * of a bug in user's configuration.)


 605      * When this property is {@link Boolean#FALSE}, it means that
 606      * the pipeline does not expect a reply from a server (and therefore
 607      * the correlator should not block for a reply message
 608      * -- if such a reply does arrive, it can be just ignored.)
 609      *
 610      * <p>
 611      * When this property is {@link Boolean#TRUE}, it means that
 612      * the pipeline expects a reply from a server (and therefore
 613      * the correlator should block to see if a reply message is received,
 614      *
 615      * <p>
 616      * This property is always set to {@link Boolean#TRUE} or
 617      * {@link Boolean#FALSE} when used on the request message
 618      * on the client side.
 619      * No other {@link Boolean} instances are allowed.
 620      * <p>
 621      *
 622      * In all other situations, this property is null.
 623      *
 624      */
 625     @com.sun.xml.internal.ws.api.PropertySet.Property(BindingProviderProperties.ONE_WAY_OPERATION)
 626     public Boolean expectReply;
 627 
 628 
 629     /**
 630      * This property will be removed in a near future.
 631      *
 632      * <p>
 633      * A part of what this flag represented moved to
 634      * {@link #expectReply} and the other part was moved
 635      * to {@link Message#isOneWay(WSDLPort)}. Please update
 636      * your code soon, or risk breaking your build!!
 637      */
 638     @Deprecated
 639     public Boolean isOneWay;
 640 
 641     /**
 642      * Indicates whether is invoking a synchronous pattern. If true, no
 643      * async client programming model (e.g. AsyncResponse or AsyncHandler)
 644      * were used to make the request that created this packet.
 645      */
 646     public Boolean isSynchronousMEP;
 647 
 648     /**
 649      * Indicates whether a non-null AsyncHandler was given at the point of
 650      * making the request that created this packet. This flag can be used
 651      * by Tube implementations to decide how to react when isSynchronousMEP
 652      * is false. If true, the client gave a non-null AsyncHandler instance
 653      * at the point of request, and will be expecting a response on that
 654      * handler when this request has been processed.
 655      */
 656     public Boolean nonNullAsyncHandlerGiven;
 657 
 658     /**














 659      * Lazily created set of handler-scope property names.
 660      *
 661      * <p>
 662      * We expect that this is only used when handlers are present
 663      * and they explicitly set some handler-scope values.
 664      *
 665      * @see #getHandlerScopePropertyNames(boolean)
 666      */
 667     private Set<String> handlerScopePropertyNames;
 668 
 669     /**
 670      * Bag to capture properties that are available for the whole
 671      * message invocation (namely on both requests and responses.)
 672      *
 673      * <p>
 674      * These properties are copied from a request to a response.
 675      * This is where we keep properties that are set by handlers.
 676      *
 677      * <p>
 678      * See <a href="#properties">class javadoc</a> for more discussion.


 684     /**
 685      * Gets a {@link Set} that stores handler-scope properties.
 686      *
 687      * <p>
 688      * These properties will not be exposed to the response context.
 689      * Consequently, if a {@link Tube} wishes to hide a property
 690      * to {@link ResponseContext}, it needs to add the property name
 691      * to this set.
 692      *
 693      * @param readOnly
 694      *      Return true if the caller only intends to read the value of this set.
 695      *      Internally, the {@link Set} is allocated lazily, and this flag helps
 696      *      optimizing the strategy.
 697      *
 698      * @return
 699      *      always non-null, possibly empty set that stores property names.
 700      */
 701     public final Set<String> getHandlerScopePropertyNames(boolean readOnly) {
 702         Set<String> o = this.handlerScopePropertyNames;
 703         if (o == null) {
 704             if (readOnly)
 705                 return Collections.emptySet();

 706             o = new HashSet<String>();
 707             this.handlerScopePropertyNames = o;
 708         }
 709         return o;
 710     }
 711 
 712     /**
 713      * This method no longer works.
 714      *
 715      * @deprecated
 716      *      Use {@link #getHandlerScopePropertyNames(boolean)}.
 717      *      To be removed once Tango components are updated.
 718      */
 719     public final Set<String> getApplicationScopePropertyNames(boolean readOnly) {
 720         assert false;
 721         return new HashSet<String>();
 722     }
 723 
 724     /**
 725      * Creates a response {@link Packet} from a request packet ({@code this}).


 738      */
 739     @Deprecated
 740     public Packet createResponse(Message msg) {
 741         Packet response = new Packet(this);
 742         response.setMessage(msg);
 743         return response;
 744     }
 745 
 746     /**
 747      * Creates a response {@link Packet} from a request packet ({@code this}).
 748      *
 749      * <p>
 750      * When a {@link Packet} for a reply is created, some properties need to be
 751      * copied over from a request to a response, and this method handles it correctly.
 752      *
 753      * @param msg
 754      *      The {@link Message} that represents a reply. Can be null.
 755      */
 756     public Packet createClientResponse(Message msg) {
 757         Packet response = new Packet(this);
 758         response.soapAction = null; // de-initializing
 759         response.setMessage(msg);

 760         return response;
 761     }
 762 
 763     /**














 764      * Creates a server-side response {@link Packet} from a request
 765      * packet ({@code this}). If WS-Addressing is enabled, a default Action
 766      * Message Addressing Property is obtained using <code>wsdlPort</code> {@link WSDLPort}
 767      * and <code>binding</code> {@link WSBinding}.
 768      * <p><p>
 769      * This method should be called to create application response messages
 770      * since they are associated with a {@link WSBinding} and {@link WSDLPort}.
 771      * For creating protocol messages that require a non-default Action, use
 772      * {@link #createServerResponse(Message, com.sun.xml.internal.ws.api.addressing.AddressingVersion, com.sun.xml.internal.ws.api.SOAPVersion, String)}.
 773      *
 774      * @param responseMessage The {@link Message} that represents a reply. Can be null.
 775      * @param wsdlPort The response WSDL port.
 776      * @param binding The response Binding. Cannot be null.
 777      * @return response packet
 778      */
 779     public Packet createServerResponse(@Nullable Message responseMessage, @Nullable WSDLPort wsdlPort, @Nullable SEIModel seiModel, @NotNull WSBinding binding) {
 780         Packet r = createClientResponse(responseMessage);


 781 
 782         AddressingVersion av = binding.getAddressingVersion();
 783         // populate WS-A headers only if WS-A is enabled
 784         if (av == null)
 785             return r;
 786         //populate WS-A headers only if the request has addressing headers
 787         String inputAction = this.getMessage().getHeaders().getAction(av, binding.getSOAPVersion());
 788         if (inputAction == null) {
 789             return r;
 790         }
 791         // if one-way, then dont populate any WS-A headers
 792         if (responseMessage == null || (wsdlPort != null && message.isOneWay(wsdlPort)))
 793             return r;
 794 
 795         // otherwise populate WS-Addressing headers
 796         populateAddressingHeaders(binding, r, wsdlPort, seiModel);
 797         return r;



















 798     }



 799 

























 800 
 801     public Packet relateServerResponse(@Nullable Packet r, @Nullable WSDLPort wsdlPort, @Nullable SEIModel seiModel, @NotNull WSBinding binding) {
 802         copySatelliteInto((DistributedPropertySet) r);
 803         r.soapAction = null;
 804         r.handlerConfig = this.handlerConfig;
 805         r.invocationProperties.putAll(this.invocationProperties);
 806         r.handlerScopePropertyNames = this.handlerScopePropertyNames;
 807         r.contentNegotiation = this.contentNegotiation;
 808         r.wasTransportSecure = this.wasTransportSecure;
 809         r.endpointAddress = this.endpointAddress;
 810         r.wsdlOperation = this.wsdlOperation;
 811 
 812         r.acceptableMimeTypes = this.acceptableMimeTypes;
 813         r.endpoint = this.endpoint;
 814         r.proxy = this.proxy;
 815         r.webServiceContextDelegate = this.webServiceContextDelegate;
 816         r.expectReply = this.expectReply;
 817 



 818         AddressingVersion av = binding.getAddressingVersion();
 819         // populate WS-A headers only if WS-A is enabled
 820         if (av == null)




 821             return r;


 822         //populate WS-A headers only if the request has addressing headers
 823         String inputAction = this.getMessage().getHeaders().getAction(av, binding.getSOAPVersion());
 824         if (inputAction == null) {
 825             return r;
 826         }
 827         // if one-way, then dont populate any WS-A headers
 828         if (r.getMessage() == null || (wsdlPort != null && message.isOneWay(wsdlPort)))
 829             return r;

 830 
 831         // otherwise populate WS-Addressing headers
 832         populateAddressingHeaders(binding, r, wsdlPort, seiModel);
 833         return r;
 834     }
 835 
 836     /**
 837      * Creates a server-side response {@link Packet} from a request
 838      * packet ({@code this}). If WS-Addressing is enabled, <code>action</code>
 839      * is used as Action Message Addressing Property.
 840      * <p><p>
 841      * This method should be called only for creating protocol response messages
 842      * that require a particular value of Action since they are not associated
 843      * with a {@link WSBinding} and {@link WSDLPort} but do know the {@link AddressingVersion}
 844      * and {@link SOAPVersion}.
 845      *
 846      * @param responseMessage The {@link Message} that represents a reply. Can be null.
 847      * @param addressingVersion The WS-Addressing version of the response message.
 848      * @param soapVersion The SOAP version of the response message.
 849      * @param action The response Action Message Addressing Property value.
 850      * @return response packet
 851      */
 852     public Packet createServerResponse(@Nullable Message responseMessage, @NotNull AddressingVersion addressingVersion, @NotNull SOAPVersion soapVersion, @NotNull String action) {
 853         Packet responsePacket = createClientResponse(responseMessage);
 854 
 855         // populate WS-A headers only if WS-A is enabled
 856         if (addressingVersion == null)
 857             return responsePacket;

 858         //populate WS-A headers only if the request has addressing headers
 859         String inputAction = this.getMessage().getHeaders().getAction(addressingVersion, soapVersion);
 860         if (inputAction == null) {
 861             return responsePacket;
 862         }
 863 
 864         populateAddressingHeaders(responsePacket, addressingVersion, soapVersion, action, false);
 865         return responsePacket;
 866     }
 867 
 868     /**
 869      * Overwrites the {@link Message} of the response packet ({@code this}) by the given {@link Message}.
 870      * Unlike {@link #setMessage(Message)}, fill in the addressing headers correctly, and this process
 871      * requires the access to the request packet.
 872      *
 873      * <p>
 874      * This method is useful when the caller needs to swap a response message completely to a new one.
 875      *
 876      * @see #createServerResponse(Message, AddressingVersion, SOAPVersion, String)
 877      */
 878     public void setResponseMessage(@NotNull Packet request, @Nullable Message responseMessage, @NotNull AddressingVersion addressingVersion, @NotNull SOAPVersion soapVersion, @NotNull String action) {
 879         Packet temp = request.createServerResponse(responseMessage, addressingVersion, soapVersion, action);
 880         setMessage(temp.getMessage());
 881     }
 882 
 883     private void populateAddressingHeaders(Packet responsePacket, AddressingVersion av, SOAPVersion sv, String action, boolean mustUnderstand) {
 884         // populate WS-A headers only if WS-A is enabled
 885         if (av == null) return;
 886 
 887         // if one-way, then dont populate any WS-A headers
 888         if (responsePacket.getMessage() == null)
 889             return;
 890 
 891         HeaderList hl = responsePacket.getMessage().getHeaders();
 892 
 893         WsaPropertyBag wpb = getSatellite(WsaPropertyBag.class);
 894 
 895         // wsa:To
 896         WSEndpointReference replyTo = null;
 897         if (wpb != null)
 898                 replyTo = wpb.getReplyToFromRequest();
 899         if (replyTo == null)
 900                 replyTo = message.getHeaders().getReplyTo(av, sv);












 901 
 902         // wsa:Action, add if the message doesn't already contain it,
 903         // generally true for SEI case where there is SEIModel or WSDLModel
 904         //           false for Provider with no wsdl, Expects User to set the coresponding header on the Message.
 905         if (responsePacket.getMessage().getHeaders().getAction(av, sv) == null) {
 906             //wsa:Action header is not set in the message, so use the wsa:Action  passed as the parameter.
 907             hl.add(new StringHeader(av.actionTag, action, sv, mustUnderstand));
 908         }
 909 
 910         // wsa:MessageID
 911         if (responsePacket.getMessage().getHeaders().get(av.messageIDTag, false) == null) {
 912             // if header doesn't exist, method getID creates a new random id
 913             String newID = Message.generateMessageID();
 914             hl.add(new StringHeader(av.messageIDTag, newID));
 915         }
 916 
 917         // wsa:RelatesTo
 918         String mid = null;
 919         if (wpb != null)
 920                 mid = wpb.getMessageID();
 921         if (mid == null)
 922                 mid = message.getHeaders().getMessageID(av, sv);
 923         if (mid != null)
 924             hl.add(new RelatesToHeader(av.relatesToTag, mid));



 925 
 926 
 927         // populate reference parameters
 928         WSEndpointReference refpEPR = null;
 929         if (responsePacket.getMessage().isFault()) {
 930             // choose FaultTo
 931                 if (wpb != null)
 932                         refpEPR = wpb.getFaultToFromRequest();
 933                 if (refpEPR == null)
 934                         refpEPR = message.getHeaders().getFaultTo(av, sv);


 935             // if FaultTo is null, then use ReplyTo
 936             if (refpEPR == null)
 937                 refpEPR = replyTo;

 938         } else {
 939             // choose ReplyTo
 940             refpEPR = replyTo;
 941         }
 942         if (refpEPR != null) {
 943             hl.add(new StringHeader(av.toTag, refpEPR.getAddress()));
 944             refpEPR.addReferenceParametersToList(hl);
 945         }
 946     }
 947 
 948     private void populateAddressingHeaders(WSBinding binding, Packet responsePacket, WSDLPort wsdlPort, SEIModel seiModel) {
 949         AddressingVersion addressingVersion = binding.getAddressingVersion();
 950 
 951         if (addressingVersion == null) return;


 952 
 953         WsaTubeHelper wsaHelper = addressingVersion.getWsaHelper(wsdlPort, seiModel, binding);
 954         String action = responsePacket.message.isFault() ?
 955                 wsaHelper.getFaultAction(this, responsePacket) :
 956                 wsaHelper.getOutputAction(this);
 957         if (action == null) {
 958             LOGGER.info("WSA headers are not added as value for wsa:Action cannot be resolved for this message");
 959             return;
 960         }
 961         populateAddressingHeaders(responsePacket, addressingVersion, binding.getSOAPVersion(), action, addressingVersion.isRequired(binding));
 962     }
 963 
 964     public String toShortString() {
 965       return super.toString();
 966     }
 967 
 968     // For use only in a debugger

 969     public String toString() {
 970       StringBuilder buf = new StringBuilder();
 971       buf.append(super.toString());
 972       String content;
 973         try {
 974         if (message != null) {

 975                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
 976                         XMLStreamWriter xmlWriter = XMLStreamWriterFactory.create(baos, "UTF-8");
 977                         message.copy().writeTo(xmlWriter);
 978                         xmlWriter.flush();
 979                         xmlWriter.close();
 980                         baos.flush();
 981                         XMLStreamWriterFactory.recycle(xmlWriter);
 982 
 983                         byte[] bytes = baos.toByteArray();
 984                         //message = Messages.create(XMLStreamReaderFactory.create(null, new ByteArrayInputStream(bytes), "UTF-8", true));
 985                         content = new String(bytes, "UTF-8");
 986                 } else {
 987                     content = "<none>";
 988         }
 989         } catch (Throwable t) {
 990                 throw new WebServiceException(t);
 991         }
 992       buf.append(" Content: ").append(content);
 993       return buf.toString();
 994     }
 995 
 996     // completes TypedMap
 997     private static final PropertyMap model;
 998 
 999     static {
1000         model = parse(Packet.class);
1001     }
1002 

1003     protected PropertyMap getPropertyMap() {
1004         return model;
1005     }
1006 






















































































1007     private static final Logger LOGGER = Logger.getLogger(Packet.class.getName());
1008 

1009     public SOAPMessage getSOAPMessage() throws SOAPException {
1010         return (message != null) ? message.readAsSOAPMessage() : null;











1011     }
1012 

1013     Codec codec = null;
1014     Codec getCodec() {
1015         if (codec != null) return codec;


1016         if (endpoint != null) {
1017             codec = endpoint.createCodec();
1018         }
1019         WSBinding wsb = getBinding();
1020         if (wsb != null) {
1021             codec = wsb.getBindingId().createEncoder(wsb);
1022         }
1023         return codec;
1024     }
1025 
1026 
1027     public ContentType writeTo( OutputStream out ) throws IOException {





1028         return getCodec().encode(this, out);
1029     }
1030 
1031     public ContentType writeTo( WritableByteChannel buffer ) {
1032         return getCodec().encode(this, buffer);























































































































































































































1033     }
1034 }
   1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.xml.internal.ws.api.message;
  27 
  28 import com.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;
  64 
  65 

  66 import org.w3c.dom.Document;
  67 import org.w3c.dom.Element;
  68 import org.xml.sax.SAXException;
  69 
  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;
  83 
  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;
  90 
  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>


 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 {
 163 
 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     }
 179 
 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     }
 186 
 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     }
 194 
 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     }
 213 
 214     private Message message;
 215 
 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     }
 227 
 228     public Message getInternalMessage() {
 229         return (message instanceof MessageWrapper)? ((MessageWrapper)message).delegate : message;
 230     }
 231 
 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     }
 250 
 251     private WSDLOperationMapping wsdlOperationMapping = null;
 252 
 253     private QName wsdlOperation;
 254 
 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     }
 273 
 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     }
 293 
 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     }
 304 
 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.


 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";
 333 
 334     /**
 335      *
 336      */
 337     public static final String HA_INFO = "com.sun.xml.internal.ws.api.message.packet.hainfo";
 338 
 339 
 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;
 347 
 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;
 356 
 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;
 364 
 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;
 375 
 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;
 388 
 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     }
 403 
 404     public void setEndPointAddressString(String s) {
 405         if (s == null) {
 406             this.endpointAddress = null;
 407         } else {
 408             this.endpointAddress = EndpointAddress.create(s);
 409         }
 410     }
 411 
 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;
 419 
 420     @Property(ContentNegotiation.PROPERTY)
 421     public String getContentNegotiationString() {
 422         return (contentNegotiation != null) ? contentNegotiation.toString() : null;
 423     }
 424 
 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     }
 437 
 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     }
 480 
 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     }
 493 
 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;
 508 
 509     /**
 510      * When non-null, this object is consulted to
 511      * implement {@link WebServiceContext} methods


 543      *      The previous value of {@link #transportBackChannel}.
 544      */
 545     public TransportBackChannel keepTransportBackChannelOpen() {
 546         TransportBackChannel r = transportBackChannel;
 547         transportBackChannel = null;
 548         return r;
 549     }
 550 
 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;
 556 
 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;
 565 
 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;
 592 
 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.)


 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;
 653 
 654 
 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;
 666 
 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;
 673 
 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;
 683 
 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; }
 697 
 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;
 708 
 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.


 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     }
 752 
 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     }
 764 
 765     /**
 766      * Creates a response {@link Packet} from a request packet ({@code this}).


 779      */
 780     @Deprecated
 781     public Packet createResponse(Message msg) {
 782         Packet response = new Packet(this);
 783         response.setMessage(msg);
 784         return response;
 785     }
 786 
 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     }
 803 
 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     }
 812 
 813     private void finishCreateRelateClientResponse(final Packet response) {
 814         response.soapAction = null; // de-initializing
 815         response.setState(State.ClientResponse);
 816     }
 817 
 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     }
 838 
 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     }



 846 
 847 
 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;
 859 
 860         if (!isCopy) { //is relate
 861           request = this;
 862           response = packet;
 863 
 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;
 873 
 874           // processing specific properties
 875           response.soapAction = request.soapAction;
 876           response.setState(request.getState());
 877         }
 878 
 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     }
 899 
















 900 
 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         }
 909 
 910         if (getMessage() == null) {
 911             return r;
 912         }
 913 
 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         }
 923 
 924         // otherwise populate WS-Addressing headers
 925         populateAddressingHeaders(binding, r, wsdlPort, seiModel);
 926         return r;
 927     }
 928 
 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         }
 957 
 958         populateAddressingHeaders(responsePacket, addressingVersion, soapVersion, action, false);
 959         return responsePacket;
 960     }
 961 
 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     }
 976 
 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;
 980 
 981         // if one-way, then dont populate any WS-A headers
 982         if (responsePacket.getMessage() == null)
 983             return;
 984 
 985         MessageHeaders hl = responsePacket.getMessage().getHeaders();
 986 
 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;
1000             }
1001         } catch (XMLStreamException e) {
1002             throw new WebServiceException(AddressingMessages.REPLY_TO_CANNOT_PARSE(), e);
1003         }
1004         if (replyTo == null) {
1005               replyTo = AddressingUtils.getReplyTo(msg.getHeaders(), av, sv);
1006         }
1007 
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));
1014         }
1015 
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));
1021         }
1022 
1023         // wsa:RelatesTo
1024         String mid = null;
1025         if (wpb != null) {
1026             mid = wpb.getMessageID();
1027         }
1028         if (mid == null) {
1029             mid = AddressingUtils.getMessageID(msg.getHeaders(), av, sv);
1030         }
1031         if (mid != null) {
1032             hl.addOrReplace(new RelatesToHeader(av.relatesToTag, mid));
1033         }
1034 
1035 
1036         // populate reference parameters
1037         WSEndpointReference refpEPR = null;
1038         if (responsePacket.getMessage().isFault()) {
1039             // choose FaultTo
1040             if (wpb != null) {
1041                 refpEPR = wpb.getFaultToFromRequest();
1042             }
1043             if (refpEPR == null) {
1044                 refpEPR = AddressingUtils.getFaultTo(msg.getHeaders(), av, sv);
1045             }
1046             // if FaultTo is null, then use ReplyTo
1047             if (refpEPR == null) {
1048                 refpEPR = replyTo;
1049             }
1050         } else {
1051             // choose ReplyTo
1052             refpEPR = replyTo;
1053         }
1054         if (replaceToTag && refpEPR != null) {
1055             hl.addOrReplace(new StringHeader(av.toTag, refpEPR.getAddress()));
1056             refpEPR.addReferenceParametersToList(hl);
1057         }
1058     }
1059 
1060     private void populateAddressingHeaders(WSBinding binding, Packet responsePacket, WSDLPort wsdlPort, SEIModel seiModel) {
1061         AddressingVersion addressingVersion = binding.getAddressingVersion();
1062 
1063         if (addressingVersion == null) {
1064             return;
1065         }
1066 
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;
1074         }
1075         populateAddressingHeaders(responsePacket, addressingVersion, binding.getSOAPVersion(), action, AddressingVersion.isRequired(binding));
1076     }
1077 
1078     public String toShortString() {
1079       return super.toString();
1080     }
1081 
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);
1098 
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>";
1104         }
1105         } catch (Throwable t) {
1106                 throw new WebServiceException(t);
1107         }
1108       buf.append(" Content: ").append(content);
1109       return buf.toString();
1110     }
1111 
1112     // completes TypedMap
1113     private static final PropertyMap model;
1114 
1115     static {
1116         model = parse(Packet.class);
1117     }
1118 
1119     @Override
1120     protected PropertyMap getPropertyMap() {
1121         return model;
1122     }
1123 
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;
1132 
1133                 return invocationProperties.get(key);
1134             }
1135 
1136             @Override
1137             public int size() {
1138                 return asMap.size() + invocationProperties.size();
1139             }
1140 
1141             @Override
1142             public boolean containsKey(Object key) {
1143                 if (asMap.containsKey(key))
1144                     return true;
1145                 return invocationProperties.containsKey(key);
1146             }
1147 
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();
1152 
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();
1158 
1159                         return new Iterator<Entry<String, Object>>() {
1160                             @Override
1161                             public boolean hasNext() {
1162                                 return asMapIt.hasNext() || ipIt.hasNext();
1163                             }
1164 
1165                             @Override
1166                             public java.util.Map.Entry<String, Object> next() {
1167                                 if (asMapIt.hasNext())
1168                                     return asMapIt.next();
1169                                 return ipIt.next();
1170                             }
1171 
1172                             @Override
1173                             public void remove() {
1174                                 throw new UnsupportedOperationException();
1175                             }
1176                         };
1177                     }
1178 
1179                     @Override
1180                     public int size() {
1181                         return asMap.size() + invocationProperties.size();
1182                     }
1183                 };
1184             }
1185 
1186             @Override
1187             public Object put(String key, Object value) {
1188                 if (supports(key))
1189                     return asMap.put(key, value);
1190 
1191                 return invocationProperties.put(key, value);
1192             }
1193 
1194             @Override
1195             public void clear() {
1196                 asMap.clear();
1197                 invocationProperties.clear();
1198             }
1199 
1200             @Override
1201             public Object remove(Object key) {
1202                 if (supports(key))
1203                     return asMap.remove(key);
1204 
1205                 return invocationProperties.remove(key);
1206             }
1207         };
1208     }
1209 
1210     private static final Logger LOGGER = Logger.getLogger(Packet.class.getName());
1211 
1212     @Override
1213     public SOAPMessage getSOAPMessage() throws SOAPException {
1214         return getAsSOAPMessage();
1215     }
1216 
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());
1226     }
1227 
1228     public
1229     Codec codec = null;
1230     public Codec getCodec() {
1231         if (codec != null) {
1232             return codec;
1233         }
1234         if (endpoint != null) {
1235             codec = endpoint.createCodec();
1236         }
1237         WSBinding wsb = getBinding();
1238         if (wsb != null) {
1239             codec = wsb.getBindingId().createEncoder(wsb);
1240         }
1241         return codec;
1242     }
1243 
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);
1250         }
1251         return getCodec().encode(this, out);
1252     }
1253 
1254     public com.oracle.webservices.internal.api.message.ContentType writeTo( WritableByteChannel buffer ) {
1255         return getCodec().encode(this, buffer);
1256     }
1257 
1258     private ContentType contentType;
1259 
1260     /**
1261      * If the request's Content-Type is multipart/related; type=application/xop+xml, then this set to to true
1262      *
1263      * Used on server-side, for encoding the repsonse.
1264      */
1265     private Boolean mtomRequest;
1266 
1267     /**
1268      * Based on request's Accept header this is set.
1269      * Currently only set if MTOMFeature is enabled.
1270      *
1271      * Should be used on server-side, for encoding the response.
1272      */
1273     private Boolean mtomAcceptable;
1274 
1275     private MTOMFeature mtomFeature;
1276 
1277     public Boolean getMtomRequest() {
1278         return mtomRequest;
1279     }
1280 
1281     public void setMtomRequest(Boolean mtomRequest) {
1282         this.mtomRequest = mtomRequest;
1283     }
1284 
1285     public Boolean getMtomAcceptable() {
1286         return mtomAcceptable;
1287     }
1288 
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;
1304             }
1305         }
1306         mtomAcceptable = checkMtomAcceptable;
1307     }
1308 
1309     private Boolean fastInfosetAcceptable;
1310 
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);
1317             }
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;
1328         }
1329         return fastInfosetAcceptable;
1330     }
1331 
1332 
1333     public void setMtomFeature(MTOMFeature mtomFeature) {
1334         this.mtomFeature = mtomFeature;
1335     }
1336 
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);
1343         }
1344         return mtomFeature;
1345     }
1346 
1347     @Override
1348     public com.oracle.webservices.internal.api.message.ContentType getContentType() {
1349         if (contentType == null) {
1350             contentType = getInternalContentType();
1351         }
1352         if (contentType == null) {
1353             contentType = getCodec().getStaticContentType(this);
1354         }
1355         if (contentType == null) {
1356             //TODO write to buffer
1357         }
1358         return contentType;
1359     }
1360 
1361     public ContentType getInternalContentType() {
1362         Message msg = getInternalMessage();
1363         if (msg instanceof MessageWritable) {
1364             return ((MessageWritable)msg).getContentType();
1365         }
1366         return contentType;
1367     }
1368 
1369     public void setContentType(ContentType contentType) {
1370         this.contentType = contentType;
1371     }
1372 
1373     public enum Status {
1374         Request, Response, Unknown;
1375         public boolean isRequest()  { return Request.equals(this); }
1376         public boolean isResponse() { return Response.equals(this); }
1377     }
1378 
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;
1384         }
1385         public boolean isInbound() {
1386             return inbound;
1387         }
1388     }
1389 
1390 //    private Status status = Status.Unknown;
1391 
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;
1395 
1396 //    public Status getStatus() { return status; }
1397 
1398     public State getState() { return state; }
1399     public void setState(State state) { this.state = state; }
1400 
1401     public boolean shouldUseMtom() {
1402         if (getState().isInbound()) {
1403             return isMtomContentType();
1404         } else {
1405             return shouldUseMtomOutbound();
1406         }
1407     }
1408 
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;
1422                 }
1423                 if (getMtomRequest() != null && getMtomRequest() && getState().equals(State.ServerResponse)) {
1424                     return true;
1425                 }
1426             }
1427         }
1428         return false;
1429     }
1430 
1431     private boolean isMtomContentType() {
1432         return (getInternalContentType() != null) &&
1433         (getInternalContentType().getContentType().contains("application/xop+xml"));
1434     }
1435 
1436     /**
1437      * @deprecated
1438      */
1439     public void addSatellite(@NotNull com.sun.xml.internal.ws.api.PropertySet satellite) {
1440         super.addSatellite(satellite);
1441     }
1442 
1443     /**
1444      * @deprecated
1445      */
1446     public void addSatellite(@NotNull Class keyClass, @NotNull com.sun.xml.internal.ws.api.PropertySet satellite) {
1447         super.addSatellite(keyClass, satellite);
1448     }
1449 
1450     /**
1451      * @deprecated
1452      */
1453     public void copySatelliteInto(@NotNull com.sun.xml.internal.ws.api.DistributedPropertySet r) {
1454         super.copySatelliteInto(r);
1455     }
1456 
1457     /**
1458      * @deprecated
1459      */
1460     public void removeSatellite(com.sun.xml.internal.ws.api.PropertySet satellite) {
1461         super.removeSatellite(satellite);
1462     }
1463 
1464     /**
1465      * This is propogated from SOAPBindingCodec and will affect isMtomAcceptable and isFastInfosetAcceptable
1466      */
1467     private boolean isFastInfosetDisabled;
1468 
1469     public void setFastInfosetDisabled(boolean b) {
1470         isFastInfosetDisabled = b;
1471     }
1472 }