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.messaging.saaj.soap; 27 28 import java.io.*; 29 import java.util.Iterator; 30 import java.util.logging.Logger; 31 import java.util.logging.Level; 32 33 import javax.activation.DataHandler; 34 import javax.activation.DataSource; 35 import javax.xml.soap.*; 36 import javax.xml.transform.Source; 37 import javax.xml.transform.stream.StreamSource; 38 39 import org.w3c.dom.*; 40 41 import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.MimeBodyPart; 42 43 import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl; 44 import com.sun.xml.internal.messaging.saaj.soap.impl.ElementImpl; 45 import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl; 46 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl; 47 import com.sun.xml.internal.messaging.saaj.util.*; 48 49 import javax.xml.transform.dom.DOMSource; 50 import javax.xml.transform.sax.SAXSource; 51 52 /** 53 * SOAPPartImpl is the first attachment. This contains the XML/SOAP document. 54 * 55 * @author Anil Vijendran (anil@sun.com) 56 */ 57 public abstract class SOAPPartImpl extends SOAPPart implements SOAPDocument { 58 protected static final Logger log = 59 Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, 60 "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); 61 62 protected MimeHeaders headers; 63 protected Envelope envelope; 64 protected Source source; 65 protected SOAPDocumentImpl document; 66 67 //flag to indicate if a setContent happened. 68 private boolean sourceWasSet = false; 69 70 // Records whether the input source had an xml decl or not. 71 protected boolean omitXmlDecl = true; 72 73 // Records the charset encoding of the input stream source if provided. 74 protected String sourceCharsetEncoding = null; 75 76 /** 77 * Reference to containing message (may be null) 78 */ 79 protected MessageImpl message; 80 81 static final boolean lazyContentLength; 82 static { 83 lazyContentLength = SAAJUtil.getSystemBoolean("saaj.lazy.contentlength"); 84 } 85 86 protected SOAPPartImpl() { 87 this(null); 88 } 89 90 protected SOAPPartImpl(MessageImpl message) { 91 document = new SOAPDocumentImpl(this); 92 headers = new MimeHeaders(); 93 this.message = message; 94 headers.setHeader("Content-Type", getContentType()); 95 } 96 97 protected abstract String getContentType(); 98 protected abstract Envelope createEnvelopeFromSource() 99 throws SOAPException; 100 protected abstract Envelope createEmptyEnvelope(String prefix) 101 throws SOAPException; 102 protected abstract SOAPPartImpl duplicateType(); 103 104 protected String getContentTypeString() { 105 return getContentType(); 106 } 107 108 public boolean isFastInfoset() { 109 return (message != null) ? message.isFastInfoset() : false; 110 } 111 112 public SOAPEnvelope getEnvelope() throws SOAPException { 113 114 // If there is no SOAP envelope already created, then create 115 // one from a source if one exists. If there is a newer source 116 // then use that source. 117 118 if (sourceWasSet) 119 sourceWasSet = false; 120 121 lookForEnvelope(); 122 if (envelope != null) { 123 if (source != null) { // there's a newer source, use it 124 document.removeChild(envelope); 125 envelope = createEnvelopeFromSource(); 126 } 127 } else if (source != null) { 128 envelope = createEnvelopeFromSource(); 129 } else { 130 envelope = createEmptyEnvelope(null); 131 document.insertBefore(envelope, null); 132 } 133 return envelope; 134 } 135 136 protected void lookForEnvelope() throws SOAPException { 137 Element envelopeChildElement = document.doGetDocumentElement(); 138 if (envelopeChildElement == null || envelopeChildElement instanceof Envelope) { 139 envelope = (EnvelopeImpl) envelopeChildElement; 140 } else if (!(envelopeChildElement instanceof ElementImpl)) { 141 log.severe("SAAJ0512.soap.incorrect.factory.used"); 142 throw new SOAPExceptionImpl("Unable to create envelope: incorrect factory used during tree construction"); 143 } else { 144 ElementImpl soapElement = (ElementImpl) envelopeChildElement; 145 if (soapElement.getLocalName().equalsIgnoreCase("Envelope")) { 146 String prefix = soapElement.getPrefix(); 147 String uri = (prefix == null) ? soapElement.getNamespaceURI() : soapElement.getNamespaceURI(prefix); 148 if(!uri.equals(NameImpl.SOAP11_NAMESPACE) && !uri.equals(NameImpl.SOAP12_NAMESPACE)) { 149 log.severe("SAAJ0513.soap.unknown.ns"); 150 throw new SOAPVersionMismatchException("Unable to create envelope from given source because the namespace was not recognized"); 151 } 152 } else { 153 log.severe("SAAJ0514.soap.root.elem.not.named.envelope"); 154 throw new SOAPExceptionImpl( 155 "Unable to create envelope from given source because the root element is not named \"Envelope\""); 156 } 157 } 158 } 159 160 public void removeAllMimeHeaders() { 161 headers.removeAllHeaders(); 162 } 163 164 public void removeMimeHeader(String header) { 165 headers.removeHeader(header); 166 } 167 168 public String[] getMimeHeader(String name) { 169 return headers.getHeader(name); 170 } 171 172 public void setMimeHeader(String name, String value) { 173 headers.setHeader(name, value); 174 } 175 176 public void addMimeHeader(String name, String value) { 177 headers.addHeader(name, value); 178 } 179 180 public Iterator getAllMimeHeaders() { 181 return headers.getAllHeaders(); 182 } 183 184 public Iterator getMatchingMimeHeaders(String[] names) { 185 return headers.getMatchingHeaders(names); 186 } 187 188 public Iterator getNonMatchingMimeHeaders(String[] names) { 189 return headers.getNonMatchingHeaders(names); 190 } 191 192 public Source getContent() throws SOAPException { 193 if (source != null) { 194 InputStream bis = null; 195 if (source instanceof JAXMStreamSource) { 196 StreamSource streamSource = (StreamSource)source; 197 bis = streamSource.getInputStream(); 198 } else if (FastInfosetReflection.isFastInfosetSource(source)) { 199 // FastInfosetSource inherits from SAXSource 200 SAXSource saxSource = (SAXSource)source; 201 bis = saxSource.getInputSource().getByteStream(); 202 } 203 204 if (bis != null) { 205 try { 206 bis.reset(); 207 } catch (IOException e) { 208 /* This exception will never be thrown. 209 * 210 * The setContent method will modify the source 211 * if StreamSource to JAXMStreamSource, that uses 212 * a ByteInputStream, and for a FastInfosetSource will 213 * replace the InputStream with a ByteInputStream. 214 */ 215 } 216 } 217 return source; 218 } 219 220 return ((Envelope) getEnvelope()).getContent(); 221 } 222 223 public void setContent(Source source) throws SOAPException { 224 try { 225 if (source instanceof StreamSource) { 226 InputStream is = ((StreamSource) source).getInputStream(); 227 Reader rdr = ((StreamSource) source).getReader(); 228 229 if (is != null) { 230 this.source = new JAXMStreamSource(is); 231 } else if (rdr != null) { 232 this.source = new JAXMStreamSource(rdr); 233 } else { 234 log.severe("SAAJ0544.soap.no.valid.reader.for.src"); 235 throw new SOAPExceptionImpl("Source does not have a valid Reader or InputStream"); 236 } 237 } 238 else if (FastInfosetReflection.isFastInfosetSource(source)) { 239 // InputStream is = source.getInputStream() 240 InputStream is = FastInfosetReflection.FastInfosetSource_getInputStream(source); 241 242 /* 243 * Underlying stream must be ByteInputStream for getContentAsStream(). We pay the 244 * cost of copying the underlying bytes here to avoid multiple copies every time 245 * getBytes() is called on a ByteInputStream. 246 */ 247 if (!(is instanceof ByteInputStream)) { 248 ByteOutputStream bout = new ByteOutputStream(); 249 bout.write(is); 250 251 // source.setInputStream(new ByteInputStream(...)) 252 FastInfosetReflection.FastInfosetSource_setInputStream( 253 source, bout.newInputStream()); 254 } 255 this.source = source; 256 } 257 else { 258 this.source = source; 259 } 260 sourceWasSet = true; 261 } 262 catch (Exception ex) { 263 ex.printStackTrace(); 264 265 log.severe("SAAJ0545.soap.cannot.set.src.for.part"); 266 throw new SOAPExceptionImpl( 267 "Error setting the source for SOAPPart: " + ex.getMessage()); 268 } 269 } 270 271 public InputStream getContentAsStream() throws IOException { 272 if (source != null) { 273 InputStream is = null; 274 275 // Allow message to be transcode if so requested 276 if (source instanceof StreamSource && !isFastInfoset()) { 277 is = ((StreamSource) source).getInputStream(); 278 } 279 else if (FastInfosetReflection.isFastInfosetSource(source) && 280 isFastInfoset()) 281 { 282 try { 283 // InputStream is = source.getInputStream() 284 is = FastInfosetReflection.FastInfosetSource_getInputStream(source); 285 } 286 catch (Exception e) { 287 throw new IOException(e.toString()); 288 } 289 } 290 291 if (is != null) { 292 if (lazyContentLength) { 293 return is; 294 } 295 if (!(is instanceof ByteInputStream)) { 296 log.severe("SAAJ0546.soap.stream.incorrect.type"); 297 throw new IOException("Internal error: stream not of the right type"); 298 } 299 return (ByteInputStream) is; 300 } 301 // need to do something here for reader... 302 // for now we'll see if we can fallback... 303 } 304 305 ByteOutputStream b = new ByteOutputStream(); 306 307 Envelope env = null; 308 309 try { 310 env = (Envelope) getEnvelope(); 311 env.output(b, isFastInfoset()); 312 } 313 catch (SOAPException soapException) { 314 log.severe("SAAJ0547.soap.cannot.externalize"); 315 throw new SOAPIOException( 316 "SOAP exception while trying to externalize: ", 317 soapException); 318 } 319 320 return b.newInputStream(); 321 } 322 323 MimeBodyPart getMimePart() throws SOAPException { 324 try { 325 MimeBodyPart headerEnvelope = new MimeBodyPart(); 326 327 headerEnvelope.setDataHandler(getDataHandler()); 328 AttachmentPartImpl.copyMimeHeaders(headers, headerEnvelope); 329 330 return headerEnvelope; 331 } catch (SOAPException ex) { 332 throw ex; 333 } catch (Exception ex) { 334 log.severe("SAAJ0548.soap.cannot.externalize.hdr"); 335 throw new SOAPExceptionImpl("Unable to externalize header", ex); 336 } 337 } 338 339 MimeHeaders getMimeHeaders() { 340 return headers; 341 } 342 343 DataHandler getDataHandler() { 344 DataSource ds = new DataSource() { 345 public OutputStream getOutputStream() throws IOException { 346 throw new IOException("Illegal Operation"); 347 } 348 349 public String getContentType() { 350 return getContentTypeString(); 351 } 352 353 public String getName() { 354 return getContentId(); 355 } 356 357 public InputStream getInputStream() throws IOException { 358 return getContentAsStream(); 359 } 360 }; 361 return new DataHandler(ds); 362 } 363 364 public SOAPDocumentImpl getDocument() { 365 handleNewSource(); 366 return document; 367 } 368 369 public SOAPPartImpl getSOAPPart() { 370 return this; 371 } 372 373 public DocumentType getDoctype() { 374 return document.getDoctype(); 375 } 376 377 // Forward all of these calls to the document to ensure that they work the 378 // same way whether they are called from here or directly from the document. 379 // If the document needs any help from this SOAPPart then 380 // Make it use a call-back as in doGetDocumentElement() below 381 public DOMImplementation getImplementation() { 382 return document.getImplementation(); 383 } 384 385 public Element getDocumentElement() { 386 // If there is no SOAP envelope already created, then create 387 // one from a source if one exists. If there is a newer source 388 // then use that source. 389 try { 390 getEnvelope(); 391 } catch (SOAPException e) { 392 } 393 return document.getDocumentElement(); 394 } 395 396 protected void doGetDocumentElement() { 397 handleNewSource(); 398 try { 399 lookForEnvelope(); 400 } catch (SOAPException e) { 401 } 402 } 403 404 public Element createElement(String tagName) throws DOMException { 405 return document.createElement(tagName); 406 } 407 408 public DocumentFragment createDocumentFragment() { 409 return document.createDocumentFragment(); 410 } 411 412 public org.w3c.dom.Text createTextNode(String data) { 413 return document.createTextNode(data); 414 } 415 416 public Comment createComment(String data) { 417 return document.createComment(data); 418 } 419 420 public CDATASection createCDATASection(String data) throws DOMException { 421 return document.createCDATASection(data); 422 } 423 424 public ProcessingInstruction createProcessingInstruction( 425 String target, 426 String data) 427 throws DOMException { 428 return document.createProcessingInstruction(target, data); 429 } 430 431 public Attr createAttribute(String name) throws DOMException { 432 return document.createAttribute(name); 433 } 434 435 public EntityReference createEntityReference(String name) 436 throws DOMException { 437 return document.createEntityReference(name); 438 } 439 440 public NodeList getElementsByTagName(String tagname) { 441 handleNewSource(); 442 return document.getElementsByTagName(tagname); 443 } 444 445 public org.w3c.dom.Node importNode( 446 org.w3c.dom.Node importedNode, 447 boolean deep) 448 throws DOMException { 449 handleNewSource(); 450 return document.importNode(importedNode, deep); 451 } 452 453 public Element createElementNS(String namespaceURI, String qualifiedName) 454 throws DOMException { 455 return document.createElementNS(namespaceURI, qualifiedName); 456 } 457 458 public Attr createAttributeNS(String namespaceURI, String qualifiedName) 459 throws DOMException { 460 return document.createAttributeNS(namespaceURI, qualifiedName); 461 } 462 463 public NodeList getElementsByTagNameNS( 464 String namespaceURI, 465 String localName) { 466 handleNewSource(); 467 return document.getElementsByTagNameNS(namespaceURI, localName); 468 } 469 470 public Element getElementById(String elementId) { 471 handleNewSource(); 472 return document.getElementById(elementId); 473 } 474 public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild) 475 throws DOMException { 476 handleNewSource(); 477 return document.appendChild(newChild); 478 } 479 480 public org.w3c.dom.Node cloneNode(boolean deep) { 481 handleNewSource(); 482 return document.cloneNode(deep); 483 } 484 485 protected SOAPPartImpl doCloneNode() { 486 handleNewSource(); 487 SOAPPartImpl newSoapPart = duplicateType(); 488 489 newSoapPart.headers = MimeHeadersUtil.copy(this.headers); 490 newSoapPart.source = this.source; 491 return newSoapPart; 492 } 493 494 public NamedNodeMap getAttributes() { 495 return document.getAttributes(); 496 } 497 498 public NodeList getChildNodes() { 499 handleNewSource(); 500 return document.getChildNodes(); 501 } 502 503 public org.w3c.dom.Node getFirstChild() { 504 handleNewSource(); 505 return document.getFirstChild(); 506 } 507 508 public org.w3c.dom.Node getLastChild() { 509 handleNewSource(); 510 return document.getLastChild(); 511 } 512 513 public String getLocalName() { 514 return document.getLocalName(); 515 } 516 517 public String getNamespaceURI() { 518 return document.getNamespaceURI(); 519 } 520 521 public org.w3c.dom.Node getNextSibling() { 522 handleNewSource(); 523 return document.getNextSibling(); 524 } 525 526 public String getNodeName() { 527 return document.getNodeName(); 528 } 529 530 public short getNodeType() { 531 return document.getNodeType(); 532 } 533 534 public String getNodeValue() throws DOMException { 535 return document.getNodeValue(); 536 } 537 538 public Document getOwnerDocument() { 539 return document.getOwnerDocument(); 540 } 541 542 public org.w3c.dom.Node getParentNode() { 543 return document.getParentNode(); 544 } 545 546 public String getPrefix() { 547 return document.getPrefix(); 548 } 549 550 public org.w3c.dom.Node getPreviousSibling() { 551 return document.getPreviousSibling(); 552 } 553 554 public boolean hasAttributes() { 555 return document.hasAttributes(); 556 } 557 558 public boolean hasChildNodes() { 559 handleNewSource(); 560 return document.hasChildNodes(); 561 } 562 563 public org.w3c.dom.Node insertBefore( 564 org.w3c.dom.Node arg0, 565 org.w3c.dom.Node arg1) 566 throws DOMException { 567 handleNewSource(); 568 return document.insertBefore(arg0, arg1); 569 } 570 571 public boolean isSupported(String arg0, String arg1) { 572 return document.isSupported(arg0, arg1); 573 } 574 575 public void normalize() { 576 handleNewSource(); 577 document.normalize(); 578 } 579 580 public org.w3c.dom.Node removeChild(org.w3c.dom.Node arg0) 581 throws DOMException { 582 handleNewSource(); 583 return document.removeChild(arg0); 584 } 585 586 public org.w3c.dom.Node replaceChild( 587 org.w3c.dom.Node arg0, 588 org.w3c.dom.Node arg1) 589 throws DOMException { 590 handleNewSource(); 591 return document.replaceChild(arg0, arg1); 592 } 593 594 public void setNodeValue(String arg0) throws DOMException { 595 document.setNodeValue(arg0); 596 } 597 598 public void setPrefix(String arg0) throws DOMException { 599 document.setPrefix(arg0); 600 } 601 602 private void handleNewSource() { 603 if (sourceWasSet) { 604 // There is a newer source use that source. 605 try { 606 getEnvelope(); 607 } catch (SOAPException e) { 608 } 609 } 610 } 611 612 protected XMLDeclarationParser lookForXmlDecl() throws SOAPException { 613 if ((source != null) && (source instanceof StreamSource)) { 614 615 Reader reader = null; 616 617 InputStream inputStream = ((StreamSource) source).getInputStream(); 618 if (inputStream != null) { 619 if (getSourceCharsetEncoding() == null) { 620 reader = new InputStreamReader(inputStream); 621 } else { 622 try { 623 reader = 624 new InputStreamReader( 625 inputStream, getSourceCharsetEncoding()); 626 } catch (UnsupportedEncodingException uee) { 627 log.log( 628 Level.SEVERE, 629 "SAAJ0551.soap.unsupported.encoding", 630 new Object[] {getSourceCharsetEncoding()}); 631 throw new SOAPExceptionImpl( 632 "Unsupported encoding " + getSourceCharsetEncoding(), 633 uee); 634 } 635 } 636 } else { 637 reader = ((StreamSource) source).getReader(); 638 } 639 if (reader != null) { 640 PushbackReader pushbackReader = 641 new PushbackReader(reader, 4096); //some size to unread <?xml ....?> 642 XMLDeclarationParser ev = 643 new XMLDeclarationParser(pushbackReader); 644 try { 645 ev.parse(); 646 } catch (Exception e) { 647 log.log( 648 Level.SEVERE, 649 "SAAJ0552.soap.xml.decl.parsing.failed"); 650 throw new SOAPExceptionImpl( 651 "XML declaration parsing failed", e); 652 } 653 String xmlDecl = ev.getXmlDeclaration(); 654 if ((xmlDecl != null) && (xmlDecl.length() > 0)) { 655 this.omitXmlDecl = false; 656 } 657 if (lazyContentLength) { 658 source = new StreamSource(pushbackReader); 659 } 660 return ev; 661 } 662 } else if ((source != null) && (source instanceof DOMSource)) { 663 //TODO: A Domsource maynot contain XMLDecl ?. 664 } 665 return null; 666 } 667 668 public void setSourceCharsetEncoding(String charset) { 669 this.sourceCharsetEncoding = charset; 670 } 671 672 public org.w3c.dom.Node renameNode(org.w3c.dom.Node n, String namespaceURI, String qualifiedName) 673 throws DOMException { 674 handleNewSource(); 675 return document.renameNode(n, namespaceURI, qualifiedName); 676 } 677 678 public void normalizeDocument() { 679 document.normalizeDocument(); 680 } 681 682 public DOMConfiguration getDomConfig() { 683 return document.getDomConfig(); 684 } 685 686 public org.w3c.dom.Node adoptNode(org.w3c.dom.Node source) throws DOMException { 687 handleNewSource(); 688 return document.adoptNode(source); 689 } 690 691 public void setDocumentURI(String documentURI) { 692 document.setDocumentURI(documentURI); 693 } 694 695 public String getDocumentURI() { 696 return document.getDocumentURI(); 697 } 698 699 public void setStrictErrorChecking(boolean strictErrorChecking) { 700 document.setStrictErrorChecking(strictErrorChecking); 701 } 702 703 public String getInputEncoding() { 704 return document.getInputEncoding(); 705 } 706 707 public String getXmlEncoding() { 708 return document.getXmlEncoding(); 709 } 710 711 public boolean getXmlStandalone() { 712 return document.getXmlStandalone(); 713 } 714 715 public void setXmlStandalone(boolean xmlStandalone) throws DOMException { 716 document.setXmlStandalone(xmlStandalone); 717 } 718 719 public String getXmlVersion() { 720 return document.getXmlVersion(); 721 } 722 723 public void setXmlVersion(String xmlVersion) throws DOMException { 724 document.setXmlVersion(xmlVersion); 725 } 726 727 public boolean getStrictErrorChecking() { 728 return document.getStrictErrorChecking(); 729 } 730 731 // DOM L3 methods from org.w3c.dom.Node 732 public String getBaseURI() { 733 return document.getBaseURI(); 734 } 735 736 public short compareDocumentPosition(org.w3c.dom.Node other) 737 throws DOMException { 738 return document.compareDocumentPosition(other); 739 } 740 741 public String getTextContent() 742 throws DOMException { 743 return document.getTextContent(); 744 } 745 746 public void setTextContent(String textContent) throws DOMException { 747 document.setTextContent(textContent); 748 } 749 750 public boolean isSameNode(org.w3c.dom.Node other) { 751 return document.isSameNode(other); 752 } 753 754 public String lookupPrefix(String namespaceURI) { 755 return document.lookupPrefix(namespaceURI); 756 } 757 758 public boolean isDefaultNamespace(String namespaceURI) { 759 return document.isDefaultNamespace(namespaceURI); 760 } 761 762 public String lookupNamespaceURI(String prefix) { 763 return document.lookupNamespaceURI(prefix); 764 } 765 766 public boolean isEqualNode(org.w3c.dom.Node arg) { 767 return document.isEqualNode(arg); 768 } 769 770 public Object getFeature(String feature, 771 String version) { 772 return document.getFeature(feature,version); 773 } 774 775 public Object setUserData(String key, 776 Object data, 777 UserDataHandler handler) { 778 return document.setUserData(key, data, handler); 779 } 780 781 public Object getUserData(String key) { 782 return document.getUserData(key); 783 } 784 785 public void recycleNode() { 786 // Nothing seems to be required to be done here 787 } 788 789 public String getValue() { 790 return null; 791 } 792 793 public void setValue(String value) { 794 log.severe("SAAJ0571.soappart.setValue.not.defined"); 795 throw new IllegalStateException("Setting value of a soap part is not defined"); 796 } 797 798 public void setParentElement(SOAPElement parent) throws SOAPException { 799 log.severe("SAAJ0570.soappart.parent.element.not.defined"); 800 throw new SOAPExceptionImpl("The parent element of a soap part is not defined"); 801 } 802 803 public SOAPElement getParentElement() { 804 return null; 805 } 806 807 public void detachNode() { 808 // Nothing seems to be required to be done here 809 } 810 811 public String getSourceCharsetEncoding() { 812 return sourceCharsetEncoding; 813 } 814 }