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