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

Fri, 14 Feb 2014 11:13:45 +0100

author
mkos
date
Fri, 14 Feb 2014 11:13:45 +0100
changeset 515
6cd506508147
parent 397
b99d7e355d4b
child 637
9c07ef4934dd
permissions
-rw-r--r--

8026188: Enhance envelope factory
Summary: Avoiding caching data initialized via TCCL in static context; fix also reviewed by Alexander Fomin
Reviewed-by: ahgross, mgrebac, skoivu

     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.message;
    28 import com.sun.istack.internal.NotNull;
    29 import com.sun.xml.internal.bind.api.Bridge;
    30 import com.sun.xml.internal.ws.api.SOAPVersion;
    31 import com.sun.xml.internal.ws.api.message.Header;
    32 import com.sun.xml.internal.ws.api.message.Message;
    33 import com.sun.xml.internal.ws.api.message.MessageHeaders;
    34 import com.sun.xml.internal.ws.api.message.MessageWritable;
    35 import com.sun.xml.internal.ws.api.message.Packet;
    36 import com.sun.xml.internal.ws.api.message.saaj.SAAJFactory;
    37 import com.sun.xml.internal.ws.encoding.TagInfoset;
    38 import com.sun.xml.internal.ws.message.saaj.SAAJMessage;
    39 import com.sun.xml.internal.ws.spi.db.XMLBridge;
    40 import java.util.ArrayList;
    41 import java.util.Collections;
    42 import org.xml.sax.ContentHandler;
    43 import org.xml.sax.ErrorHandler;
    44 import org.xml.sax.SAXException;
    45 import org.xml.sax.helpers.AttributesImpl;
    46 import org.xml.sax.helpers.LocatorImpl;
    48 import javax.xml.bind.JAXBException;
    49 import javax.xml.bind.Unmarshaller;
    50 import javax.xml.soap.SOAPException;
    51 import javax.xml.soap.SOAPMessage;
    52 import javax.xml.stream.XMLStreamException;
    53 import javax.xml.stream.XMLStreamWriter;
    54 import javax.xml.transform.Source;
    55 import javax.xml.transform.sax.SAXSource;
    57 import java.util.List;
    58 import java.util.Map;
    60 /**
    61  * Partial {@link Message} implementation.
    62  *
    63  * <p>
    64  * This class implements some of the {@link Message} methods.
    65  * The idea is that those implementations may be non-optimal but
    66  * it may save effort in implementing {@link Message} and reduce
    67  * the code size.
    68  *
    69  * <p>
    70  * {@link Message} classes that are used more commonly should
    71  * examine carefully which method can be implemented faster,
    72  * and override them accordingly.
    73  *
    74  * @author Kohsuke Kawaguchi
    75  */
    76 public abstract class AbstractMessageImpl extends Message {
    77     /**
    78      * SOAP version of this message.
    79      * Used to implement some of the methods, but nothing more than that.
    80      *
    81      * <p>
    82      * So if you aren't using those methods that use this field,
    83      * this can be null.
    84      */
    85     protected final SOAPVersion soapVersion;
    87     protected @NotNull TagInfoset envelopeTag;
    88     protected @NotNull TagInfoset headerTag;
    89     protected @NotNull TagInfoset bodyTag;
    91     protected static final AttributesImpl EMPTY_ATTS;
    92     protected static final LocatorImpl NULL_LOCATOR = new LocatorImpl();
    93     protected static final List<TagInfoset> DEFAULT_TAGS;
    95     static void create(SOAPVersion v, List c) {
    96         int base = v.ordinal()*3;
    97         c.add(base, new TagInfoset(v.nsUri, "Envelope", "S", EMPTY_ATTS,"S", v.nsUri));
    98         c.add(base+1, new TagInfoset(v.nsUri, "Header", "S", EMPTY_ATTS));
    99         c.add(base+2, new TagInfoset(v.nsUri, "Body", "S", EMPTY_ATTS));
   100     }
   102     static {
   103         EMPTY_ATTS = new AttributesImpl();
   104         List<TagInfoset> tagList = new ArrayList<TagInfoset>();
   105         create(SOAPVersion.SOAP_11, tagList);
   106         create(SOAPVersion.SOAP_12, tagList);
   107         DEFAULT_TAGS = Collections.unmodifiableList(tagList);
   108     }
   110     protected AbstractMessageImpl(SOAPVersion soapVersion) {
   111         this.soapVersion = soapVersion;
   112     }
   114     @Override
   115     public SOAPVersion getSOAPVersion() {
   116         return soapVersion;
   117     }
   118     /**
   119      * Copy constructor.
   120      */
   121     protected AbstractMessageImpl(AbstractMessageImpl that) {
   122         this.soapVersion = that.soapVersion;
   123     }
   125     @Override
   126     public Source readEnvelopeAsSource() {
   127         return new SAXSource(new XMLReaderImpl(this), XMLReaderImpl.THE_SOURCE);
   128     }
   130     @Override
   131     public <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException {
   132         if(hasAttachments())
   133             unmarshaller.setAttachmentUnmarshaller(new AttachmentUnmarshallerImpl(getAttachments()));
   134         try {
   135             return (T) unmarshaller.unmarshal(readPayloadAsSource());
   136         } finally{
   137             unmarshaller.setAttachmentUnmarshaller(null);
   138         }
   139     }
   140     /** @deprecated */
   141     @Override
   142     public <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException {
   143         return bridge.unmarshal(readPayloadAsSource(),
   144             hasAttachments()? new AttachmentUnmarshallerImpl(getAttachments()) : null );
   145     }
   147     @Override
   148     public <T> T readPayloadAsJAXB(XMLBridge<T> bridge) throws JAXBException {
   149         return bridge.unmarshal(readPayloadAsSource(),
   150             hasAttachments()? new AttachmentUnmarshallerImpl(getAttachments()) : null );
   151     }
   153     /**
   154      * Default implementation that relies on {@link #writePayloadTo(XMLStreamWriter)}
   155      */
   156     @Override
   157     public void writeTo(XMLStreamWriter w) throws XMLStreamException {
   158         String soapNsUri = soapVersion.nsUri;
   159         w.writeStartDocument();
   160         w.writeStartElement("S","Envelope",soapNsUri);
   161         w.writeNamespace("S",soapNsUri);
   162         if(hasHeaders()) {
   163             w.writeStartElement("S","Header",soapNsUri);
   164             MessageHeaders headers = getHeaders();
   165             for (Header h : headers.asList()) {
   166                 h.writeTo(w);
   167             }
   168             w.writeEndElement();
   169         }
   170         // write the body
   171         w.writeStartElement("S","Body",soapNsUri);
   173         writePayloadTo(w);
   175         w.writeEndElement();
   176         w.writeEndElement();
   177         w.writeEndDocument();
   178     }
   180     /**
   181      * Writes the whole envelope as SAX events.
   182      */
   183     @Override
   184     public void writeTo( ContentHandler contentHandler, ErrorHandler errorHandler ) throws SAXException {
   185         String soapNsUri = soapVersion.nsUri;
   187         contentHandler.setDocumentLocator(NULL_LOCATOR);
   188         contentHandler.startDocument();
   189         contentHandler.startPrefixMapping("S",soapNsUri);
   190         contentHandler.startElement(soapNsUri,"Envelope","S:Envelope",EMPTY_ATTS);
   191         if(hasHeaders()) {
   192             contentHandler.startElement(soapNsUri,"Header","S:Header",EMPTY_ATTS);
   193             MessageHeaders headers = getHeaders();
   194             for (Header h : headers.asList()) {
   195                 h.writeTo(contentHandler,errorHandler);
   196             }
   197             contentHandler.endElement(soapNsUri,"Header","S:Header");
   198         }
   199         // write the body
   200         contentHandler.startElement(soapNsUri,"Body","S:Body",EMPTY_ATTS);
   201         writePayloadTo(contentHandler,errorHandler, true);
   202         contentHandler.endElement(soapNsUri,"Body","S:Body");
   203         contentHandler.endElement(soapNsUri,"Envelope","S:Envelope");
   204     }
   206     /**
   207      * Writes the payload to SAX events.
   208      *
   209      * @param fragment
   210      *      if true, this method will fire SAX events without start/endDocument events,
   211      *      suitable for embedding this into a bigger SAX event sequence.
   212      *      if false, this method generaets a completely SAX event sequence on its own.
   213      */
   214     protected abstract void writePayloadTo(ContentHandler contentHandler, ErrorHandler errorHandler, boolean fragment) throws SAXException;
   216     public Message toSAAJ(Packet p, Boolean inbound) throws SOAPException {
   217         SAAJMessage message = SAAJFactory.read(p);
   218         if (message instanceof MessageWritable)
   219             ((MessageWritable) message)
   220                     .setMTOMConfiguration(p.getMtomFeature());
   221         if (inbound != null) transportHeaders(p, inbound, message.readAsSOAPMessage());
   222         return message;
   223     }
   225     /**
   226      * Default implementation that uses {@link #writeTo(ContentHandler, ErrorHandler)}
   227      */
   228     @Override
   229     public SOAPMessage readAsSOAPMessage() throws SOAPException {
   230         return SAAJFactory.read(soapVersion, this);
   231     }
   233     @Override
   234     public SOAPMessage readAsSOAPMessage(Packet packet, boolean inbound) throws SOAPException {
   235         SOAPMessage msg = SAAJFactory.read(soapVersion, this, packet);
   236         transportHeaders(packet, inbound, msg);
   237         return msg;
   238     }
   240     private void transportHeaders(Packet packet, boolean inbound, SOAPMessage msg) throws SOAPException {
   241         Map<String, List<String>> headers = getTransportHeaders(packet, inbound);
   242         if (headers != null) {
   243             addSOAPMimeHeaders(msg.getMimeHeaders(), headers);
   244         }
   245         if (msg.saveRequired()) msg.saveChanges();
   246     }
   247 }

mercurial