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 }