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 }