1 /*
   2  * Copyright (c) 1997, 2017, 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 /**
  27 *
  28 * @author SAAJ RI Development Team
  29 */
  30 package com.sun.xml.internal.messaging.saaj.soap;
  31 
  32 import com.sun.xml.internal.messaging.saaj.soap.impl.CDATAImpl;
  33 import com.sun.xml.internal.messaging.saaj.soap.impl.ElementFactory;
  34 import com.sun.xml.internal.messaging.saaj.soap.impl.ElementImpl;
  35 import com.sun.xml.internal.messaging.saaj.soap.impl.SOAPCommentImpl;
  36 import com.sun.xml.internal.messaging.saaj.soap.impl.SOAPTextImpl;
  37 import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl;
  38 import com.sun.xml.internal.messaging.saaj.util.LogDomainConstants;
  39 import com.sun.xml.internal.messaging.saaj.util.SAAJUtil;
  40 import org.w3c.dom.Attr;
  41 import org.w3c.dom.CDATASection;
  42 import org.w3c.dom.Comment;
  43 import org.w3c.dom.DOMConfiguration;
  44 import org.w3c.dom.DOMException;
  45 import org.w3c.dom.DOMImplementation;
  46 import org.w3c.dom.Document;
  47 import org.w3c.dom.DocumentFragment;
  48 import org.w3c.dom.DocumentType;
  49 import org.w3c.dom.Element;
  50 import org.w3c.dom.EntityReference;
  51 import org.w3c.dom.NamedNodeMap;
  52 import org.w3c.dom.Node;
  53 import org.w3c.dom.NodeList;
  54 import org.w3c.dom.ProcessingInstruction;
  55 import org.w3c.dom.UserDataHandler;
  56 
  57 import javax.xml.parsers.DocumentBuilder;
  58 import javax.xml.parsers.DocumentBuilderFactory;
  59 import javax.xml.parsers.ParserConfigurationException;
  60 import javax.xml.soap.SOAPElement;
  61 import javax.xml.soap.SOAPException;
  62 import java.text.MessageFormat;
  63 import java.util.HashMap;
  64 import java.util.Map;
  65 import java.util.logging.Logger;
  66 
  67 public class SOAPDocumentImpl implements SOAPDocument, javax.xml.soap.Node, Document {
  68 
  69     private static final String XMLNS = "xmlns".intern();
  70     protected static final Logger log =
  71         Logger.getLogger(LogDomainConstants.SOAP_DOMAIN,
  72                          "com.sun.xml.internal.messaging.saaj.soap.LocalStrings");
  73 
  74     SOAPPartImpl enclosingSOAPPart;
  75 
  76     private Document document;
  77 
  78     private Map<Node, javax.xml.soap.Node> domToSoap = new HashMap<>();
  79 
  80     public SOAPDocumentImpl(SOAPPartImpl enclosingDocument) {
  81         document = createDocument();
  82         this.enclosingSOAPPart = enclosingDocument;
  83         register(this);
  84     }
  85 
  86     private Document createDocument() {
  87         DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", SAAJUtil.getSystemClassLoader());
  88         try {
  89             final DocumentBuilder documentBuilder = docFactory.newDocumentBuilder();
  90             return documentBuilder.newDocument();
  91         } catch (ParserConfigurationException e) {
  92             throw new RuntimeException("Error creating xml document", e);
  93         }
  94     }
  95 
  96     //    public SOAPDocumentImpl(boolean grammarAccess) {
  97     //        super(grammarAccess);
  98     //    }
  99     //
 100     //    public SOAPDocumentImpl(DocumentType doctype) {
 101     //        super(doctype);
 102     //    }
 103     //
 104     //    public SOAPDocumentImpl(DocumentType doctype, boolean grammarAccess) {
 105     //        super(doctype, grammarAccess);
 106     //    }
 107 
 108     @Override
 109     public SOAPPartImpl getSOAPPart() {
 110         if (enclosingSOAPPart == null) {
 111             log.severe("SAAJ0541.soap.fragment.not.bound.to.part");
 112             throw new RuntimeException("Could not complete operation. Fragment not bound to SOAP part.");
 113         }
 114         return enclosingSOAPPart;
 115     }
 116 
 117     @Override
 118     public SOAPDocumentImpl getDocument() {
 119         return this;
 120     }
 121 
 122     @Override
 123     public DocumentType getDoctype() {
 124         // SOAP means no DTD, No DTD means no doctype (SOAP 1.2 only?)
 125         return null;
 126     }
 127 
 128     @Override
 129     public DOMImplementation getImplementation() {
 130         return document.getImplementation();
 131     }
 132 
 133     @Override
 134     public Element getDocumentElement() {
 135         // This had better be an Envelope!
 136         getSOAPPart().doGetDocumentElement();
 137         return doGetDocumentElement();
 138     }
 139 
 140     protected Element doGetDocumentElement() {
 141         return document.getDocumentElement();
 142     }
 143 
 144     @Override
 145     public Element createElement(String tagName) throws DOMException {
 146         return ElementFactory.createElement(
 147             this,
 148             NameImpl.getLocalNameFromTagName(tagName),
 149             NameImpl.getPrefixFromTagName(tagName),
 150             null);
 151     }
 152 
 153     @Override
 154     public DocumentFragment createDocumentFragment() {
 155         return document.createDocumentFragment();
 156     }
 157 
 158     @Override
 159     public org.w3c.dom.Text createTextNode(String data) {
 160         return new SOAPTextImpl(this, data);
 161     }
 162 
 163     @Override
 164     public Comment createComment(String data) {
 165         return new SOAPCommentImpl(this, data);
 166     }
 167 
 168     @Override
 169     public CDATASection createCDATASection(String data) throws DOMException {
 170         return new CDATAImpl(this, data);
 171     }
 172 
 173     @Override
 174     public ProcessingInstruction createProcessingInstruction(
 175         String target,
 176         String data)
 177         throws DOMException {
 178         log.severe("SAAJ0542.soap.proc.instructions.not.allowed.in.docs");
 179         throw new UnsupportedOperationException("Processing Instructions are not allowed in SOAP documents");
 180     }
 181 
 182     @Override
 183     public Attr createAttribute(String name) throws DOMException {
 184         boolean isQualifiedName = (name.indexOf(":") > 0);
 185         if (isQualifiedName) {
 186             String nsUri = null;
 187             String prefix = name.substring(0, name.indexOf(":"));
 188             //cannot do anything to resolve the URI if prefix is not
 189             //XMLNS.
 190             if (XMLNS.equals(prefix)) {
 191                 nsUri = ElementImpl.XMLNS_URI;
 192                 return createAttributeNS(nsUri, name);
 193             }
 194         }
 195 
 196         return document.createAttribute(name);
 197     }
 198 
 199     @Override
 200     public EntityReference createEntityReference(String name)
 201         throws DOMException {
 202             log.severe("SAAJ0543.soap.entity.refs.not.allowed.in.docs");
 203             throw new UnsupportedOperationException("Entity References are not allowed in SOAP documents");
 204     }
 205 
 206     @Override
 207     public NodeList getElementsByTagName(String tagname) {
 208         return document.getElementsByTagName(tagname);
 209     }
 210 
 211     @Override
 212     public org.w3c.dom.Node importNode(Node importedNode, boolean deep)
 213         throws DOMException {
 214         final Node node = document.importNode(getDomNode(importedNode), deep);
 215         return node instanceof Element ?
 216             ElementFactory.createElement(this, (Element) node)
 217                 : node;
 218     }
 219 
 220     @Override
 221     public Element createElementNS(String namespaceURI, String qualifiedName)
 222         throws DOMException {
 223         return ElementFactory.createElement(
 224             this,
 225             NameImpl.getLocalNameFromTagName(qualifiedName),
 226             NameImpl.getPrefixFromTagName(qualifiedName),
 227             namespaceURI);
 228     }
 229 
 230     @Override
 231     public Attr createAttributeNS(String namespaceURI, String qualifiedName)
 232         throws DOMException {
 233         return document.createAttributeNS(namespaceURI, qualifiedName);
 234     }
 235 
 236     @Override
 237     public NodeList getElementsByTagNameNS(
 238         String namespaceURI,
 239         String localName) {
 240         return document.getElementsByTagNameNS(namespaceURI, localName);
 241     }
 242 
 243     @Override
 244     public Element getElementById(String elementId) {
 245         return document.getElementById(elementId);
 246     }
 247 
 248     @Override
 249     public String getInputEncoding() {
 250         return document.getInputEncoding();
 251     }
 252 
 253     @Override
 254     public String getXmlEncoding() {
 255         return document.getXmlEncoding();
 256     }
 257 
 258     @Override
 259     public boolean getXmlStandalone() {
 260         return document.getXmlStandalone();
 261     }
 262 
 263     @Override
 264     public void setXmlStandalone(boolean xmlStandalone) throws DOMException {
 265         document.setXmlStandalone(xmlStandalone);
 266     }
 267 
 268     @Override
 269     public String getXmlVersion() {
 270         return document.getXmlVersion();
 271     }
 272 
 273     @Override
 274     public void setXmlVersion(String xmlVersion) throws DOMException {
 275         document.setXmlVersion(xmlVersion);
 276     }
 277 
 278     @Override
 279     public boolean getStrictErrorChecking() {
 280         return document.getStrictErrorChecking();
 281     }
 282 
 283     @Override
 284     public void setStrictErrorChecking(boolean strictErrorChecking) {
 285         document.setStrictErrorChecking(strictErrorChecking);
 286     }
 287 
 288     @Override
 289     public String getDocumentURI() {
 290         return document.getDocumentURI();
 291     }
 292 
 293     @Override
 294     public void setDocumentURI(String documentURI) {
 295         document.setDocumentURI(documentURI);
 296     }
 297 
 298     @Override
 299     public Node adoptNode(Node source) throws DOMException {
 300         return document.adoptNode(source);
 301     }
 302 
 303     @Override
 304     public DOMConfiguration getDomConfig() {
 305         return document.getDomConfig();
 306     }
 307 
 308     @Override
 309     public void normalizeDocument() {
 310         document.normalizeDocument();
 311     }
 312 
 313     @Override
 314     public Node renameNode(Node n, String namespaceURI, String qualifiedName) throws DOMException {
 315         return document.renameNode(n, namespaceURI, qualifiedName);
 316     }
 317 
 318     @Override
 319     public String getNodeName() {
 320         return document.getNodeName();
 321     }
 322 
 323     @Override
 324     public String getNodeValue() throws DOMException {
 325         return document.getNodeValue();
 326     }
 327 
 328     @Override
 329     public void setNodeValue(String nodeValue) throws DOMException {
 330         document.setNodeValue(nodeValue);
 331     }
 332 
 333     @Override
 334     public short getNodeType() {
 335         return document.getNodeType();
 336     }
 337 
 338     @Override
 339     public Node getParentNode() {
 340         return document.getParentNode();
 341     }
 342 
 343     @Override
 344     public NodeList getChildNodes() {
 345         return document.getChildNodes();
 346     }
 347 
 348     @Override
 349     public Node getFirstChild() {
 350         return document.getFirstChild();
 351     }
 352 
 353     @Override
 354     public Node getLastChild() {
 355         return document.getLastChild();
 356     }
 357 
 358     @Override
 359     public Node getPreviousSibling() {
 360         return document.getPreviousSibling();
 361     }
 362 
 363     @Override
 364     public Node getNextSibling() {
 365         return document.getNextSibling();
 366     }
 367 
 368     @Override
 369     public NamedNodeMap getAttributes() {
 370         return document.getAttributes();
 371     }
 372 
 373     @Override
 374     public Document getOwnerDocument() {
 375         return document.getOwnerDocument();
 376     }
 377 
 378     @Override
 379     public Node insertBefore(Node newChild, Node refChild) throws DOMException {
 380         return document.insertBefore(getDomNode(newChild), getDomNode(refChild));
 381     }
 382 
 383     @Override
 384     public Node replaceChild(Node newChild, Node oldChild) throws DOMException {
 385         return document.replaceChild(getDomNode(newChild), getDomNode(oldChild));
 386     }
 387 
 388     @Override
 389     public Node removeChild(Node oldChild) throws DOMException {
 390         return document.removeChild(getDomNode(oldChild));
 391     }
 392 
 393     @Override
 394     public Node appendChild(Node newChild) throws DOMException {
 395         return document.appendChild(getDomNode(newChild));
 396     }
 397 
 398     @Override
 399     public boolean hasChildNodes() {
 400         return document.hasChildNodes();
 401     }
 402 
 403     @Override
 404     public Node cloneNode(boolean deep) {
 405         return document.cloneNode(deep);
 406     }
 407 
 408     @Override
 409     public void normalize() {
 410         document.normalize();
 411     }
 412 
 413     @Override
 414     public boolean isSupported(String feature, String version) {
 415         return document.isSupported(feature, version);
 416     }
 417 
 418     @Override
 419     public String getNamespaceURI() {
 420         return document.getNamespaceURI();
 421     }
 422 
 423     @Override
 424     public String getPrefix() {
 425         return document.getPrefix();
 426     }
 427 
 428     @Override
 429     public void setPrefix(String prefix) throws DOMException {
 430         document.setPrefix(prefix);
 431     }
 432 
 433     @Override
 434     public String getLocalName() {
 435         return document.getLocalName();
 436     }
 437 
 438     @Override
 439     public boolean hasAttributes() {
 440         return document.hasAttributes();
 441     }
 442 
 443     @Override
 444     public String getBaseURI() {
 445         return document.getBaseURI();
 446     }
 447 
 448     @Override
 449     public short compareDocumentPosition(Node other) throws DOMException {
 450         return document.compareDocumentPosition(other);
 451     }
 452 
 453     @Override
 454     public String getTextContent() throws DOMException {
 455         return document.getTextContent();
 456     }
 457 
 458     @Override
 459     public void setTextContent(String textContent) throws DOMException {
 460         document.setTextContent(textContent);
 461     }
 462 
 463     @Override
 464     public boolean isSameNode(Node other) {
 465         return document.isSameNode(other);
 466     }
 467 
 468     @Override
 469     public String lookupPrefix(String namespaceURI) {
 470         return document.lookupPrefix(namespaceURI);
 471     }
 472 
 473     @Override
 474     public boolean isDefaultNamespace(String namespaceURI) {
 475         return document.isDefaultNamespace(namespaceURI);
 476     }
 477 
 478     @Override
 479     public String lookupNamespaceURI(String prefix) {
 480         return document.lookupNamespaceURI(prefix);
 481     }
 482 
 483     @Override
 484     public boolean isEqualNode(Node arg) {
 485         return document.isEqualNode(arg);
 486     }
 487 
 488     @Override
 489     public Object getFeature(String feature, String version) {
 490         return document.getFeature(feature, version);
 491     }
 492 
 493     @Override
 494     public Object setUserData(String key, Object data, UserDataHandler handler) {
 495         return document.setUserData(key, data, handler);
 496     }
 497 
 498     @Override
 499     public Object getUserData(String key) {
 500         return document.getUserData(key);
 501     }
 502 
 503     public Document getDomDocument() {
 504         return document;
 505     }
 506 
 507     /**
 508      * Insert a mapping information for {@link org.w3c.dom.Node} - {@link javax.xml.soap.Node}.
 509      *
 510      * In SAAJ, elements in DOM are expected to be interfaces of SAAJ, on the other hand in JDKs Xerces,
 511      * they are casted to internal impl classes. After removal of SAAJ dependency
 512      * to JDKs internal classes elements in DOM can never be both of them.
 513      *
 514      * @param node SAAJ wrapper node for w3c DOM node
 515      */
 516     public void register(javax.xml.soap.Node node) {
 517         final Node domElement = getDomNode(node);
 518         if (domToSoap.containsKey(domElement)) {
 519             throw new IllegalStateException("Element " + domElement.getNodeName()
 520                     + " is already registered");
 521         }
 522         domToSoap.put(domElement, node);
 523     }
 524 
 525     /**
 526      * Find a soap wrapper for w3c dom node.
 527      *
 528      * @param node w3c dom node nullable
 529      * @return soap wrapper for w3c dom node
 530      *
 531      * @throws
 532      */
 533     public javax.xml.soap.Node find(Node node) {
 534         return find(node, true);
 535     }
 536 
 537     private javax.xml.soap.Node find(Node node, boolean required) {
 538         if (node == null) {
 539             return null;
 540         }
 541         if (node instanceof javax.xml.soap.Node) {
 542             return (javax.xml.soap.Node) node;
 543         }
 544         final javax.xml.soap.Node found = domToSoap.get(node);
 545         if (found == null && required) {
 546             throw new IllegalArgumentException(MessageFormat.format("Cannot find SOAP wrapper for element {0}", node));
 547         }
 548         return found;
 549     }
 550 
 551     /**
 552      * If corresponding soap wrapper exists for w3c dom node it is returned,
 553      * if not passed dom element is returned.
 554      *
 555      * @param node w3c dom node
 556      * @return soap wrapper or passed w3c dom node if not found
 557      */
 558     public Node findIfPresent(Node node) {
 559         final javax.xml.soap.Node found = find(node, false);
 560         return found != null ? found : node;
 561     }
 562 
 563     /**
 564      * Extracts w3c dom node from corresponding soap wrapper.
 565      *
 566      * @param node soap or dom nullable
 567      * @return dom node
 568      */
 569     public Node getDomNode(Node node) {
 570         if (node instanceof SOAPDocumentImpl) {
 571             return ((SOAPDocumentImpl)node).getDomElement();
 572         } else if (node instanceof ElementImpl) {
 573             return ((ElementImpl) node).getDomElement();
 574         } else if (node instanceof SOAPTextImpl) {
 575             return ((SOAPTextImpl)node).getDomElement();
 576         } else if (node instanceof SOAPCommentImpl) {
 577             return ((SOAPCommentImpl)node).getDomElement();
 578         } else if (node instanceof CDATAImpl) {
 579             return ((CDATAImpl) node).getDomElement();
 580         }
 581         return node;
 582     }
 583 
 584     public Document getDomElement() {
 585         return document;
 586     }
 587 
 588     @Override
 589     public String getValue() {
 590         throw new UnsupportedOperationException();
 591     }
 592 
 593     @Override
 594     public void setValue(String value) {
 595         throw new UnsupportedOperationException();
 596     }
 597 
 598     @Override
 599     public void setParentElement(SOAPElement parent) throws SOAPException {
 600         throw new UnsupportedOperationException();
 601     }
 602 
 603     @Override
 604     public SOAPElement getParentElement() {
 605         throw new UnsupportedOperationException();
 606     }
 607 
 608     @Override
 609     public void detachNode() {
 610         throw new UnsupportedOperationException();
 611     }
 612 
 613     @Override
 614     public void recycleNode() {
 615         throw new UnsupportedOperationException();
 616     }
 617 }