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

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

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

merge

     1 /*
     2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.xml.internal.ws.message.saaj;
    28 import com.sun.istack.internal.FragmentContentHandler;
    29 import com.sun.istack.internal.NotNull;
    30 import com.sun.istack.internal.Nullable;
    31 import com.sun.istack.internal.XMLStreamException2;
    32 import com.sun.xml.internal.bind.api.Bridge;
    33 import com.sun.xml.internal.bind.unmarshaller.DOMScanner;
    34 import com.sun.xml.internal.ws.api.SOAPVersion;
    35 import com.sun.xml.internal.ws.api.message.*;
    36 import com.sun.xml.internal.ws.message.AttachmentUnmarshallerImpl;
    37 import com.sun.xml.internal.ws.spi.db.XMLBridge;
    38 import com.sun.xml.internal.ws.streaming.DOMStreamReader;
    39 import com.sun.xml.internal.ws.util.ASCIIUtility;
    40 import com.sun.xml.internal.ws.util.DOMUtil;
    41 import org.w3c.dom.Attr;
    42 import org.w3c.dom.Element;
    43 import org.w3c.dom.NamedNodeMap;
    44 import org.w3c.dom.Node;
    45 import org.xml.sax.ContentHandler;
    46 import org.xml.sax.ErrorHandler;
    47 import org.xml.sax.SAXException;
    48 import org.xml.sax.helpers.AttributesImpl;
    49 import org.xml.sax.helpers.LocatorImpl;
    51 import javax.activation.DataHandler;
    52 import javax.xml.bind.JAXBException;
    53 import javax.xml.bind.Unmarshaller;
    54 import javax.xml.soap.*;
    55 import javax.xml.stream.XMLStreamException;
    56 import javax.xml.stream.XMLStreamReader;
    57 import javax.xml.stream.XMLStreamWriter;
    58 import javax.xml.transform.Source;
    59 import javax.xml.transform.dom.DOMSource;
    60 import javax.xml.transform.stream.StreamSource;
    61 import javax.xml.ws.WebServiceException;
    62 import java.io.IOException;
    63 import java.io.InputStream;
    64 import java.io.OutputStream;
    65 import java.util.HashMap;
    66 import java.util.Iterator;
    67 import java.util.List;
    68 import java.util.Map;
    70 /**
    71  * {@link Message} implementation backed by {@link SOAPMessage}.
    72  *
    73  * @author Vivek Pandey
    74  * @author Rama Pulavarthi
    75  */
    76 public class SAAJMessage extends Message {
    77     // flag to switch between representations
    78     private boolean parsedMessage;
    79     // flag to check if Message API is exercised;
    80     private boolean accessedMessage;
    81     private final SOAPMessage sm;
    83     private MessageHeaders headers;
    84     private List<Element> bodyParts;
    85     private Element payload;
    87     private String payloadLocalName;
    88     private String payloadNamespace;
    89     private SOAPVersion soapVersion;
    91     //Collect the attrbutes on the enclosing elements so that the same message can be reproduced without loss of any
    92     // valuable info
    93     private NamedNodeMap bodyAttrs, headerAttrs, envelopeAttrs;
    95     public SAAJMessage(SOAPMessage sm) {
    96         this.sm = sm;
    97     }
    99     /**
   100      * This constructor is a convenience and called by the {@link #copy}
   101      *
   102      * @param headers
   103      * @param sm
   104      */
   105     private SAAJMessage(MessageHeaders headers, AttachmentSet as, SOAPMessage sm, SOAPVersion version) {
   106         this.sm = sm;
   107         this.parse();
   108         if(headers == null)
   109             headers = new HeaderList(version);
   110         this.headers = headers;
   111         this.attachmentSet = as;
   112     }
   114     private void parse() {
   115         if (!parsedMessage) {
   116             try {
   117                 access();
   118                 if (headers == null)
   119                     headers = new HeaderList(getSOAPVersion());
   120                 SOAPHeader header = sm.getSOAPHeader();
   121                 if (header != null) {
   122                     headerAttrs = header.getAttributes();
   123                     Iterator iter = header.examineAllHeaderElements();
   124                     while (iter.hasNext()) {
   125                         headers.add(new SAAJHeader((SOAPHeaderElement) iter.next()));
   126                     }
   127                 }
   128                 attachmentSet = new SAAJAttachmentSet(sm);
   130                 parsedMessage = true;
   131             } catch (SOAPException e) {
   132                 throw new WebServiceException(e);
   133             }
   134         }
   135     }
   137     protected void access() {
   138         if (!accessedMessage) {
   139             try {
   140                 envelopeAttrs = sm.getSOAPPart().getEnvelope().getAttributes();
   141                 Node body = sm.getSOAPBody();
   142                 bodyAttrs = body.getAttributes();
   143                 soapVersion = SOAPVersion.fromNsUri(body.getNamespaceURI());
   144                 //cature all the body elements
   145                 bodyParts = DOMUtil.getChildElements(body);
   146                 //we treat payload as the first body part
   147                 payload = bodyParts.size() > 0 ? bodyParts.get(0) : null;
   148                 // hope this is correct. Caching the localname and namespace of the payload should be fine
   149                 // but what about if a Handler replaces the payload with something else? Weel, may be it
   150                 // will be error condition anyway
   151                 if (payload != null) {
   152                     payloadLocalName = payload.getLocalName();
   153                     payloadNamespace = payload.getNamespaceURI();
   154                 }
   155                 accessedMessage = true;
   156             } catch (SOAPException e) {
   157                 throw new WebServiceException(e);
   158             }
   159         }
   160     }
   162     public boolean hasHeaders() {
   163         parse();
   164         return headers.hasHeaders();
   165     }
   167     public @NotNull MessageHeaders getHeaders() {
   168         parse();
   169         return headers;
   170     }
   172     /**
   173      * Gets the attachments of this message
   174      * (attachments live outside a message.)
   175      */
   176     @Override
   177     public @NotNull AttachmentSet getAttachments() {
   178         if (attachmentSet == null) attachmentSet = new SAAJAttachmentSet(sm);
   179         return attachmentSet;
   180     }
   182     /**
   183      * Optimization hint for the derived class to check
   184      * if we may have some attachments.
   185      */
   186     @Override
   187     protected boolean hasAttachments() {
   188         return !getAttachments().isEmpty();
   189     }
   191     public @Nullable String getPayloadLocalPart() {
   192         soapBodyFirstChild();
   193         return payloadLocalName;
   194     }
   196     public String getPayloadNamespaceURI() {
   197         soapBodyFirstChild();
   198         return payloadNamespace;
   199     }
   201     public boolean hasPayload() {
   202         return soapBodyFirstChild() != null;
   203     }
   205     private void addAttributes(Element e, NamedNodeMap attrs) {
   206         if(attrs == null)
   207             return;
   208         String elPrefix = e.getPrefix();
   209         for(int i=0; i < attrs.getLength();i++) {
   210             Attr a = (Attr)attrs.item(i);
   211             //check if attr is ns declaration
   212             if("xmlns".equals(a.getPrefix()) || "xmlns".equals(a.getLocalName())) {
   213                 if(elPrefix == null && a.getLocalName().equals("xmlns")) {
   214                     // the target element has already default ns declaration, dont' override it
   215                     continue;
   216                 } else if(elPrefix != null && "xmlns".equals(a.getPrefix()) && elPrefix.equals(a.getLocalName())) {
   217                     //dont bind the prefix to ns again, its already in the target element.
   218                     continue;
   219                 }
   220                 e.setAttributeNS(a.getNamespaceURI(),a.getName(),a.getValue());
   221                 continue;
   222             }
   223             e.setAttributeNS(a.getNamespaceURI(),a.getName(),a.getValue());
   224         }
   225     }
   227     public Source readEnvelopeAsSource() {
   228         try {
   229             if (!parsedMessage) {
   230                 SOAPEnvelope se = sm.getSOAPPart().getEnvelope();
   231                 return new DOMSource(se);
   233             } else {
   234                                 SOAPMessage msg = soapVersion.getMessageFactory().createMessage();
   235                 addAttributes(msg.getSOAPPart().getEnvelope(),envelopeAttrs);
   237                 SOAPBody newBody = msg.getSOAPPart().getEnvelope().getBody();
   238                 addAttributes(newBody, bodyAttrs);
   239                 for (Element part : bodyParts) {
   240                     Node n = newBody.getOwnerDocument().importNode(part, true);
   241                     newBody.appendChild(n);
   242                 }
   243                 addAttributes(msg.getSOAPHeader(),headerAttrs);
   244                 for (Header header : headers.asList()) {
   245                     header.writeTo(msg);
   246                 }
   247                 SOAPEnvelope se = msg.getSOAPPart().getEnvelope();
   248                 return new DOMSource(se);
   249             }
   250         } catch (SOAPException e) {
   251             throw new WebServiceException(e);
   252         }
   253     }
   255     public SOAPMessage readAsSOAPMessage() throws SOAPException {
   256         if (!parsedMessage) {
   257             return sm;
   258         } else {
   259             SOAPMessage msg = soapVersion.getMessageFactory().createMessage();
   260             addAttributes(msg.getSOAPPart().getEnvelope(),envelopeAttrs);
   261             SOAPBody newBody = msg.getSOAPPart().getEnvelope().getBody();
   262             addAttributes(newBody, bodyAttrs);
   263             for (Element part : bodyParts) {
   264                 Node n = newBody.getOwnerDocument().importNode(part, true);
   265                 newBody.appendChild(n);
   266             }
   267             addAttributes(msg.getSOAPHeader(),headerAttrs);
   268             for (Header header : headers.asList()) {
   269               header.writeTo(msg);
   270             }
   271             for (Attachment att : getAttachments()) {
   272               AttachmentPart part = msg.createAttachmentPart();
   273               part.setDataHandler(att.asDataHandler());
   274               part.setContentId('<' + att.getContentId() + '>');
   275               addCustomMimeHeaders(att, part);
   276               msg.addAttachmentPart(part);
   277             }
   278             msg.saveChanges();
   279             return msg;
   280         }
   281     }
   283         private void addCustomMimeHeaders(Attachment att, AttachmentPart part) {
   284                 if (att instanceof AttachmentEx) {
   285                         Iterator<AttachmentEx.MimeHeader> allMimeHeaders = ((AttachmentEx) att).getMimeHeaders();
   286                         while (allMimeHeaders.hasNext()) {
   287                                 AttachmentEx.MimeHeader mh = allMimeHeaders.next();
   288                                 String name = mh.getName();
   289                                 if (!"Content-Type".equalsIgnoreCase(name)
   290                                                 && !"Content-Id".equalsIgnoreCase(name)) {
   291                                         part.addMimeHeader(name, mh.getValue());
   292                                 }
   293                         }
   294                 }
   295         }
   297     public Source readPayloadAsSource() {
   298         access();
   299         return (payload != null) ? new DOMSource(payload) : null;
   300     }
   302     public <T> T readPayloadAsJAXB(Unmarshaller unmarshaller) throws JAXBException {
   303         access();
   304         if (payload != null) {
   305             if(hasAttachments())
   306                 unmarshaller.setAttachmentUnmarshaller(new AttachmentUnmarshallerImpl(getAttachments()));
   307             return (T) unmarshaller.unmarshal(payload);
   309         }
   310         return null;
   311     }
   313     /** @deprecated */
   314     public <T> T readPayloadAsJAXB(Bridge<T> bridge) throws JAXBException {
   315         access();
   316         if (payload != null)
   317             return bridge.unmarshal(payload,hasAttachments()? new AttachmentUnmarshallerImpl(getAttachments()) : null);
   318         return null;
   319     }
   320     public <T> T readPayloadAsJAXB(XMLBridge<T> bridge) throws JAXBException {
   321         access();
   322         if (payload != null)
   323             return bridge.unmarshal(payload,hasAttachments()? new AttachmentUnmarshallerImpl(getAttachments()) : null);
   324         return null;
   325     }
   327     public XMLStreamReader readPayload() throws XMLStreamException {
   328         return soapBodyFirstChildReader();
   329     }
   331     public void writePayloadTo(XMLStreamWriter sw) throws XMLStreamException {
   332         access();
   333         try {
   334             for (Element part : bodyParts)
   335                 DOMUtil.serializeNode(part, sw);
   336         } catch (XMLStreamException e) {
   337             throw new WebServiceException(e);
   338         }
   339     }
   341     public void writeTo(XMLStreamWriter writer) throws XMLStreamException {
   342         try {
   343             writer.writeStartDocument();
   344             if (!parsedMessage) {
   345                 DOMUtil.serializeNode(sm.getSOAPPart().getEnvelope(), writer);
   346             } else {
   347                 SOAPEnvelope env = sm.getSOAPPart().getEnvelope();
   348                 DOMUtil.writeTagWithAttributes(env, writer);
   349                 if (hasHeaders()) {
   350                     if(env.getHeader() != null) {
   351                         DOMUtil.writeTagWithAttributes(env.getHeader(), writer);
   352                     } else {
   353                         writer.writeStartElement(env.getPrefix(), "Header", env.getNamespaceURI());
   354                     }
   355                     for (Header h : headers.asList()) {
   356                         h.writeTo(writer);
   357                     }
   358                     writer.writeEndElement();
   359                 }
   361                 DOMUtil.serializeNode(sm.getSOAPBody(), writer);
   362                 writer.writeEndElement();
   363             }
   364             writer.writeEndDocument();
   365             writer.flush();
   366         } catch (SOAPException ex) {
   367             throw new XMLStreamException2(ex);
   368             //for now. ask jaxws team what to do.
   369         }
   370     }
   372     public void writeTo(ContentHandler contentHandler, ErrorHandler errorHandler) throws SAXException {
   373         String soapNsUri = soapVersion.nsUri;
   374         if (!parsedMessage) {
   375             DOMScanner ds = new DOMScanner();
   376             ds.setContentHandler(contentHandler);
   377             ds.scan(sm.getSOAPPart());
   378         } else {
   379             contentHandler.setDocumentLocator(NULL_LOCATOR);
   380             contentHandler.startDocument();
   381             contentHandler.startPrefixMapping("S", soapNsUri);
   382             startPrefixMapping(contentHandler, envelopeAttrs,"S");
   383             contentHandler.startElement(soapNsUri, "Envelope", "S:Envelope", getAttributes(envelopeAttrs));
   384             if (hasHeaders()) {
   385                 startPrefixMapping(contentHandler, headerAttrs,"S");
   386                 contentHandler.startElement(soapNsUri, "Header", "S:Header", getAttributes(headerAttrs));
   387                 MessageHeaders headers = getHeaders();
   388                 for (Header h : headers.asList()) {
   389                     h.writeTo(contentHandler, errorHandler);
   390                 }
   391                 endPrefixMapping(contentHandler, headerAttrs,"S");
   392                 contentHandler.endElement(soapNsUri, "Header", "S:Header");
   394             }
   395             startPrefixMapping(contentHandler, bodyAttrs,"S");
   396             // write the body
   397             contentHandler.startElement(soapNsUri, "Body", "S:Body", getAttributes(bodyAttrs));
   398             writePayloadTo(contentHandler, errorHandler, true);
   399             endPrefixMapping(contentHandler, bodyAttrs,"S");
   400             contentHandler.endElement(soapNsUri, "Body", "S:Body");
   401             endPrefixMapping(contentHandler, envelopeAttrs,"S");
   402             contentHandler.endElement(soapNsUri, "Envelope", "S:Envelope");
   403         }
   404     }
   405     /**
   406      * Gets the Attributes that are not namesapce declarations
   407      * @param attrs
   408      * @return
   409      */
   410     private AttributesImpl getAttributes(NamedNodeMap attrs) {
   411         AttributesImpl atts = new AttributesImpl();
   412         if(attrs == null)
   413             return EMPTY_ATTS;
   414         for(int i=0; i < attrs.getLength();i++) {
   415             Attr a = (Attr)attrs.item(i);
   416             //check if attr is ns declaration
   417             if("xmlns".equals(a.getPrefix()) || "xmlns".equals(a.getLocalName())) {
   418               continue;
   419             }
   420             atts.addAttribute(fixNull(a.getNamespaceURI()),a.getLocalName(),a.getName(),a.getSchemaTypeInfo().getTypeName(),a.getValue());
   421         }
   422         return atts;
   423     }
   425     /**
   426      * Collects the ns declarations and starts the prefix mapping, consequently the associated endPrefixMapping needs to be called.
   427      * @param contentHandler
   428      * @param attrs
   429      * @param excludePrefix , this is to excldue the global prefix mapping "S" used at the start
   430      * @throws SAXException
   431      */
   432     private void startPrefixMapping(ContentHandler contentHandler, NamedNodeMap attrs, String excludePrefix) throws SAXException {
   433         if(attrs == null)
   434             return;
   435         for(int i=0; i < attrs.getLength();i++) {
   436             Attr a = (Attr)attrs.item(i);
   437             //check if attr is ns declaration
   438             if("xmlns".equals(a.getPrefix()) || "xmlns".equals(a.getLocalName())) {
   439                 if(!fixNull(a.getPrefix()).equals(excludePrefix)) {
   440                     contentHandler.startPrefixMapping(fixNull(a.getPrefix()), a.getNamespaceURI());
   441                 }
   442             }
   443         }
   444     }
   446     private void endPrefixMapping(ContentHandler contentHandler, NamedNodeMap attrs, String excludePrefix) throws SAXException {
   447         if(attrs == null)
   448             return;
   449         for(int i=0; i < attrs.getLength();i++) {
   450             Attr a = (Attr)attrs.item(i);
   451             //check if attr is ns declaration
   452             if("xmlns".equals(a.getPrefix()) || "xmlns".equals(a.getLocalName())) {
   453                 if(!fixNull(a.getPrefix()).equals(excludePrefix)) {
   454                     contentHandler.endPrefixMapping(fixNull(a.getPrefix()));
   455                 }
   456             }
   457         }
   458     }
   460     private static String fixNull(String s) {
   461         if(s==null) return "";
   462         else        return s;
   463     }
   465     private void writePayloadTo(ContentHandler contentHandler, ErrorHandler errorHandler, boolean fragment) throws SAXException {
   466         if(fragment)
   467             contentHandler = new FragmentContentHandler(contentHandler);
   468         DOMScanner ds = new DOMScanner();
   469         ds.setContentHandler(contentHandler);
   470         ds.scan(payload);
   471     }
   473     /**
   474      * Creates a copy of a {@link com.sun.xml.internal.ws.api.message.Message}.
   475      * <p/>
   476      * <p/>
   477      * This method creates a new {@link com.sun.xml.internal.ws.api.message.Message} whose header/payload/attachments/properties
   478      * are identical to this {@link com.sun.xml.internal.ws.api.message.Message}. Once created, the created {@link com.sun.xml.internal.ws.api.message.Message}
   479      * and the original {@link com.sun.xml.internal.ws.api.message.Message} behaves independently --- adding header/
   480      * attachment to one {@link com.sun.xml.internal.ws.api.message.Message} doesn't affect another {@link com.sun.xml.internal.ws.api.message.Message}
   481      * at all.
   482      * <p/>
   483      * <h3>Design Rationale</h3>
   484      * <p/>
   485      * Since a {@link com.sun.xml.internal.ws.api.message.Message} body is read-once, sometimes
   486      * (such as when you do fail-over, or WS-RM) you need to
   487      * create an idential copy of a {@link com.sun.xml.internal.ws.api.message.Message}.
   488      * <p/>
   489      * <p/>
   490      * The actual copy operation depends on the layout
   491      * of the data in memory, hence it's best to be done by
   492      * the {@link com.sun.xml.internal.ws.api.message.Message} implementation itself.
   493      */
   494     public Message copy() {
   495         try {
   496             if (!parsedMessage) {
   497                 return new SAAJMessage(readAsSOAPMessage());
   498             } else {
   499                 SOAPMessage msg = soapVersion.getMessageFactory().createMessage();
   500                 SOAPBody newBody = msg.getSOAPPart().getEnvelope().getBody();
   501                 for (Element part : bodyParts) {
   502                     Node n = newBody.getOwnerDocument().importNode(part, true);
   503                     newBody.appendChild(n);
   504                 }
   505                 addAttributes(newBody, bodyAttrs);
   506                 return new SAAJMessage(getHeaders(), getAttachments(), msg, soapVersion);
   507             }
   508         } catch (SOAPException e) {
   509             throw new WebServiceException(e);
   510         }
   511     }
   512     private static final AttributesImpl EMPTY_ATTS = new AttributesImpl();
   513     private static final LocatorImpl NULL_LOCATOR = new LocatorImpl();
   515     protected static class SAAJAttachment implements AttachmentEx {
   517         final AttachmentPart ap;
   519         String contentIdNoAngleBracket;
   521         public SAAJAttachment(AttachmentPart part) {
   522             this.ap = part;
   523         }
   525         /**
   526          * Content ID of the attachment. Uniquely identifies an attachment.
   527          */
   528         public String getContentId() {
   529             if (contentIdNoAngleBracket == null) {
   530                 contentIdNoAngleBracket = ap.getContentId();
   531                 if (contentIdNoAngleBracket != null && contentIdNoAngleBracket.charAt(0) == '<')
   532                     contentIdNoAngleBracket = contentIdNoAngleBracket.substring(1, contentIdNoAngleBracket.length()-1);
   533             }
   534             return contentIdNoAngleBracket;
   535         }
   537         /**
   538          * Gets the MIME content-type of this attachment.
   539          */
   540         public String getContentType() {
   541             return ap.getContentType();
   542         }
   544         /**
   545          * Gets the attachment as an exact-length byte array.
   546          */
   547         public byte[] asByteArray() {
   548             try {
   549                 return ap.getRawContentBytes();
   550             } catch (SOAPException e) {
   551                 throw new WebServiceException(e);
   552             }
   553         }
   555         /**
   556          * Gets the attachment as a {@link javax.activation.DataHandler}.
   557          */
   558         public DataHandler asDataHandler() {
   559             try {
   560                 return ap.getDataHandler();
   561             } catch (SOAPException e) {
   562                 throw new WebServiceException(e);
   563             }
   564         }
   566         /**
   567          * Gets the attachment as a {@link javax.xml.transform.Source}.
   568          * Note that there's no guarantee that the attachment is actually an XML.
   569          */
   570         public Source asSource() {
   571             try {
   572                 return new StreamSource(ap.getRawContent());
   573             } catch (SOAPException e) {
   574                 throw new WebServiceException(e);
   575             }
   576         }
   578         /**
   579          * Obtains this attachment as an {@link java.io.InputStream}.
   580          */
   581         public InputStream asInputStream() {
   582             try {
   583                 return ap.getRawContent();
   584             } catch (SOAPException e) {
   585                 throw new WebServiceException(e);
   586             }
   587         }
   589         /**
   590          * Writes the contents of the attachment into the given stream.
   591          */
   592         public void writeTo(OutputStream os) throws IOException {
   593             try {
   594                 ASCIIUtility.copyStream(ap.getRawContent(), os);
   595             } catch (SOAPException e) {
   596                 throw new WebServiceException(e);
   597             }
   598         }
   600         /**
   601          * Writes this attachment to the given {@link javax.xml.soap.SOAPMessage}.
   602          */
   603         public void writeTo(SOAPMessage saaj) {
   604             saaj.addAttachmentPart(ap);
   605         }
   607         AttachmentPart asAttachmentPart(){
   608             return ap;
   609         }
   611                 public Iterator<MimeHeader> getMimeHeaders() {
   612                         final Iterator it = ap.getAllMimeHeaders();
   613                         return new Iterator<MimeHeader>() {
   614                                 public boolean hasNext() {
   615                                         return it.hasNext();
   616                                 }
   618                                 public MimeHeader next() {
   619                                         final javax.xml.soap.MimeHeader mh = (javax.xml.soap.MimeHeader) it.next();
   620                                         return new MimeHeader() {
   621                                                 public String getName() {
   622                                                         return mh.getName();
   623                                                 }
   625                                                 public String getValue() {
   626                                                         return mh.getValue();
   627                                                 }
   628                                         };
   629                                 }
   631                                 public void remove() {
   632                                         throw new UnsupportedOperationException();
   633                                 }
   634                         };
   635                 }
   636     }
   638     /**
   639      * {@link AttachmentSet} for SAAJ.
   640      *
   641      * SAAJ wants '&lt;' and '>' for the content ID, but {@link AttachmentSet}
   642      * doesn't. S this class also does the conversion between them.
   643      */
   644     protected static class SAAJAttachmentSet implements AttachmentSet {
   646         private Map<String, Attachment> attMap;
   647         private Iterator attIter;
   649         public SAAJAttachmentSet(SOAPMessage sm) {
   650             attIter = sm.getAttachments();
   651         }
   653         /**
   654          * Gets the attachment by the content ID.
   655          *
   656          * @return null
   657          *         if no such attachment exist.
   658          */
   659         public Attachment get(String contentId) {
   660             // if this is the first time then create the attachment Map
   661             if (attMap == null) {
   662                 if (!attIter.hasNext())
   663                     return null;
   664                 attMap = createAttachmentMap();
   665             }
   666             if(contentId.charAt(0) != '<'){
   667                 return attMap.get('<'+contentId+'>');
   668             }
   669             return attMap.get(contentId);
   670         }
   672         public boolean isEmpty() {
   673             if(attMap!=null)
   674                 return attMap.isEmpty();
   675             else
   676                 return !attIter.hasNext();
   677         }
   679         /**
   680          * Returns an iterator over a set of elements of type T.
   681          *
   682          * @return an Iterator.
   683          */
   684         public Iterator<Attachment> iterator() {
   685             if (attMap == null) {
   686                 attMap = createAttachmentMap();
   687             }
   688             return attMap.values().iterator();
   689         }
   691         private Map<String, Attachment> createAttachmentMap() {
   692             HashMap<String, Attachment> map = new HashMap<String, Attachment>();
   693             while (attIter.hasNext()) {
   694                 AttachmentPart ap = (AttachmentPart) attIter.next();
   695                 map.put(ap.getContentId(), new SAAJAttachment(ap));
   696             }
   697             return map;
   698         }
   700         public void add(Attachment att) {
   701             attMap.put('<'+att.getContentId()+'>', att);
   702         }
   703     }
   705     public SOAPVersion getSOAPVersion() {
   706         return soapVersion;
   707     }
   709     private XMLStreamReader soapBodyFirstChildReader;
   711     /**
   712      * This allow the subclass to retain the XMLStreamReader.
   713      */
   714     protected XMLStreamReader getXMLStreamReader(SOAPElement soapElement) {
   715         return null;
   716     }
   718     protected XMLStreamReader createXMLStreamReader(SOAPElement soapElement) {
   719         DOMStreamReader dss = new DOMStreamReader();
   720         dss.setCurrentNode(soapElement);
   721         return dss;
   722     }
   724     protected XMLStreamReader soapBodyFirstChildReader() {
   725         if (soapBodyFirstChildReader != null) return soapBodyFirstChildReader;
   726         soapBodyFirstChild();
   727         if (soapBodyFirstChild != null) {
   728             soapBodyFirstChildReader = getXMLStreamReader(soapBodyFirstChild);
   729             if (soapBodyFirstChildReader == null) soapBodyFirstChildReader =
   730                 createXMLStreamReader(soapBodyFirstChild);
   731             if (soapBodyFirstChildReader.getEventType() == XMLStreamReader.START_DOCUMENT) {
   732                 try {
   733                     while(soapBodyFirstChildReader.getEventType() != XMLStreamReader.START_ELEMENT)
   734                         soapBodyFirstChildReader.next();
   735                 } catch (XMLStreamException e) {
   736                     throw new RuntimeException(e);
   737                 }
   738             }
   739             return soapBodyFirstChildReader;
   740         } else {
   741             payloadLocalName = null;
   742             payloadNamespace = null;
   743             return null;
   744         }
   745     }
   747     private SOAPElement soapBodyFirstChild;
   749     SOAPElement soapBodyFirstChild() {
   750         if (soapBodyFirstChild != null) return soapBodyFirstChild;
   751         try {
   752             boolean foundElement = false;
   753             for (Node n = sm.getSOAPBody().getFirstChild(); n != null && !foundElement; n = n.getNextSibling()) {
   754                 if (n.getNodeType() == Node.ELEMENT_NODE) {
   755                     foundElement = true;
   756                     if (n instanceof SOAPElement) {
   757                         soapBodyFirstChild = (SOAPElement) n;
   758                         payloadLocalName = soapBodyFirstChild.getLocalName();
   759                         payloadNamespace = soapBodyFirstChild.getNamespaceURI();
   760                         return soapBodyFirstChild;
   761                     }
   762                 }
   763             }
   764             if(foundElement) for(Iterator i = sm.getSOAPBody().getChildElements(); i.hasNext();){
   765                 Object o = i.next();
   766                 if (o instanceof SOAPElement) {
   767                     soapBodyFirstChild = (SOAPElement)o;
   768                     payloadLocalName = soapBodyFirstChild.getLocalName();
   769                     payloadNamespace = soapBodyFirstChild.getNamespaceURI();
   770                     return soapBodyFirstChild;
   771                 }
   772             }
   773         } catch (SOAPException e) {
   774             throw new RuntimeException(e);
   775         }
   776         return soapBodyFirstChild;
   777     }
   778 }

mercurial