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