/*
 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

Author:SAAJ RI Development Team
/** * * @author SAAJ RI Development Team */
package com.sun.xml.internal.messaging.saaj.soap; import com.sun.xml.internal.messaging.saaj.soap.impl.CDATAImpl; import com.sun.xml.internal.messaging.saaj.soap.impl.ElementFactory; import com.sun.xml.internal.messaging.saaj.soap.impl.ElementImpl; import com.sun.xml.internal.messaging.saaj.soap.impl.NamedNodeMapImpl; import com.sun.xml.internal.messaging.saaj.soap.impl.NodeListImpl; import com.sun.xml.internal.messaging.saaj.soap.impl.SOAPCommentImpl; import com.sun.xml.internal.messaging.saaj.soap.impl.SOAPTextImpl; import com.sun.xml.internal.messaging.saaj.soap.name.NameImpl; import com.sun.xml.internal.messaging.saaj.util.LogDomainConstants; import com.sun.xml.internal.messaging.saaj.util.SAAJUtil; import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.CharacterData; import org.w3c.dom.Comment; import org.w3c.dom.DOMConfiguration; import org.w3c.dom.DOMException; import org.w3c.dom.DOMImplementation; import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; import org.w3c.dom.DocumentType; import org.w3c.dom.Element; import org.w3c.dom.EntityReference; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.ProcessingInstruction; import org.w3c.dom.Text; import org.w3c.dom.UserDataHandler; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.soap.SOAPElement; import javax.xml.soap.SOAPException; import java.lang.reflect.Constructor; import java.text.MessageFormat; import java.util.logging.Logger; public class SOAPDocumentImpl implements SOAPDocument, javax.xml.soap.Node, Document { public static final String SAAJ_NODE = "javax.xml.soap.Node"; private static final String XMLNS = "xmlns".intern(); protected static final Logger log = Logger.getLogger(LogDomainConstants.SOAP_DOMAIN, "com.sun.xml.internal.messaging.saaj.soap.LocalStrings"); SOAPPartImpl enclosingSOAPPart; private Document document; public SOAPDocumentImpl(SOAPPartImpl enclosingDocument) { document = createDocument(); this.enclosingSOAPPart = enclosingDocument; register(this); } private Document createDocument() { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance("com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl", SAAJUtil.getSystemClassLoader()); try { final DocumentBuilder documentBuilder = docFactory.newDocumentBuilder(); return documentBuilder.newDocument(); } catch (ParserConfigurationException e) { throw new RuntimeException("Error creating xml document", e); } } // public SOAPDocumentImpl(boolean grammarAccess) { // super(grammarAccess); // } // // public SOAPDocumentImpl(DocumentType doctype) { // super(doctype); // } // // public SOAPDocumentImpl(DocumentType doctype, boolean grammarAccess) { // super(doctype, grammarAccess); // } @Override public SOAPPartImpl getSOAPPart() { if (enclosingSOAPPart == null) { log.severe("SAAJ0541.soap.fragment.not.bound.to.part"); throw new RuntimeException("Could not complete operation. Fragment not bound to SOAP part."); } return enclosingSOAPPart; } @Override public SOAPDocumentImpl getDocument() { return this; } @Override public DocumentType getDoctype() { // SOAP means no DTD, No DTD means no doctype (SOAP 1.2 only?) return null; } @Override public DOMImplementation getImplementation() { return document.getImplementation(); } @Override public Element getDocumentElement() { // This had better be an Envelope! getSOAPPart().doGetDocumentElement(); return doGetDocumentElement(); } protected Element doGetDocumentElement() { return document.getDocumentElement(); } @Override public Element createElement(String tagName) throws DOMException { return ElementFactory.createElement( this, NameImpl.getLocalNameFromTagName(tagName), NameImpl.getPrefixFromTagName(tagName), null); } @Override public DocumentFragment createDocumentFragment() { return new SOAPDocumentFragment(this); } @Override public org.w3c.dom.Text createTextNode(String data) { return new SOAPTextImpl(this, data); } @Override public Comment createComment(String data) { return new SOAPCommentImpl(this, data); } @Override public CDATASection createCDATASection(String data) throws DOMException { return new CDATAImpl(this, data); } @Override public ProcessingInstruction createProcessingInstruction( String target, String data) throws DOMException { log.severe("SAAJ0542.soap.proc.instructions.not.allowed.in.docs"); throw new UnsupportedOperationException("Processing Instructions are not allowed in SOAP documents"); } @Override public Attr createAttribute(String name) throws DOMException { boolean isQualifiedName = (name.indexOf(":") > 0); if (isQualifiedName) { String nsUri = null; String prefix = name.substring(0, name.indexOf(":")); //cannot do anything to resolve the URI if prefix is not //XMLNS. if (XMLNS.equals(prefix)) { nsUri = ElementImpl.XMLNS_URI; return createAttributeNS(nsUri, name); } } return document.createAttribute(name); } @Override public EntityReference createEntityReference(String name) throws DOMException { log.severe("SAAJ0543.soap.entity.refs.not.allowed.in.docs"); throw new UnsupportedOperationException("Entity References are not allowed in SOAP documents"); } @Override public NodeList getElementsByTagName(String tagname) { return new NodeListImpl(this, document.getElementsByTagName(tagname)); } @Override public org.w3c.dom.Node importNode(Node importedNode, boolean deep) throws DOMException { Node domNode = getDomNode(importedNode); final Node newNode = document.importNode(domNode, deep); if (importedNode instanceof javax.xml.soap.Node) { Node newSoapNode = createSoapNode(importedNode.getClass(), newNode); newNode.setUserData(SAAJ_NODE, newSoapNode, null); if (deep && importedNode.hasChildNodes()) { NodeList childNodes = importedNode.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { registerChildNodes(childNodes.item(i), deep); } } return newSoapNode; } registerChildNodes(newNode, deep); return findIfPresent(newNode); } //If the parentNode is not registered to domToSoap, create soap wapper for parentNode and register it to domToSoap //If deep = true, also register all children of parentNode to domToSoap map. public void registerChildNodes(Node parentNode, boolean deep) { if (parentNode.getUserData(SAAJ_NODE) == null) { if (parentNode instanceof Element) { ElementFactory.createElement(this, (Element) parentNode); } else if (parentNode instanceof CharacterData) { switch (parentNode.getNodeType()) { case CDATA_SECTION_NODE: new CDATAImpl(this, (CharacterData) parentNode); break; case COMMENT_NODE: new SOAPCommentImpl(this, (CharacterData) parentNode); break; case TEXT_NODE: new SOAPTextImpl(this, (CharacterData) parentNode); break; } } } if (deep) { NodeList nodeList = parentNode.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node nextChild = nodeList.item(i); registerChildNodes(nextChild, true); } } } @Override public Element createElementNS(String namespaceURI, String qualifiedName) throws DOMException { return ElementFactory.createElement( this, NameImpl.getLocalNameFromTagName(qualifiedName), NameImpl.getPrefixFromTagName(qualifiedName), namespaceURI); } @Override public Attr createAttributeNS(String namespaceURI, String qualifiedName) throws DOMException { return document.createAttributeNS(namespaceURI, qualifiedName); } @Override public NodeList getElementsByTagNameNS( String namespaceURI, String localName) { return new NodeListImpl(this, document.getElementsByTagNameNS(namespaceURI, localName)); } @Override public Element getElementById(String elementId) { return (Element) findIfPresent(document.getElementById(elementId)); } @Override public String getInputEncoding() { return document.getInputEncoding(); } @Override public String getXmlEncoding() { return document.getXmlEncoding(); } @Override public boolean getXmlStandalone() { return document.getXmlStandalone(); } @Override public void setXmlStandalone(boolean xmlStandalone) throws DOMException { document.setXmlStandalone(xmlStandalone); } @Override public String getXmlVersion() { return document.getXmlVersion(); } @Override public void setXmlVersion(String xmlVersion) throws DOMException { document.setXmlVersion(xmlVersion); } @Override public boolean getStrictErrorChecking() { return document.getStrictErrorChecking(); } @Override public void setStrictErrorChecking(boolean strictErrorChecking) { document.setStrictErrorChecking(strictErrorChecking); } @Override public String getDocumentURI() { return document.getDocumentURI(); } @Override public void setDocumentURI(String documentURI) { document.setDocumentURI(documentURI); } @Override public Node adoptNode(Node source) throws DOMException { return document.adoptNode(source); } @Override public DOMConfiguration getDomConfig() { return document.getDomConfig(); } @Override public void normalizeDocument() { document.normalizeDocument(); } @Override public Node renameNode(Node n, String namespaceURI, String qualifiedName) throws DOMException { return findIfPresent(document.renameNode(n, namespaceURI, qualifiedName)); } @Override public String getNodeName() { return document.getNodeName(); } @Override public String getNodeValue() throws DOMException { return document.getNodeValue(); } @Override public void setNodeValue(String nodeValue) throws DOMException { document.setNodeValue(nodeValue); } @Override public short getNodeType() { return document.getNodeType(); } @Override public Node getParentNode() { return findIfPresent(document.getParentNode()); } @Override public NodeList getChildNodes() { return new NodeListImpl(this, document.getChildNodes()); } @Override public Node getFirstChild() { return findIfPresent(document.getFirstChild()); } @Override public Node getLastChild() { return findIfPresent(document.getLastChild()); } @Override public Node getPreviousSibling() { return findIfPresent(document.getPreviousSibling()); } @Override public Node getNextSibling() { return findIfPresent(document.getNextSibling()); } @Override public NamedNodeMap getAttributes() { return new NamedNodeMapImpl(document.getAttributes(), this); } @Override public Document getOwnerDocument() { return document.getOwnerDocument(); } @Override public Node insertBefore(Node newChild, Node refChild) throws DOMException { return document.insertBefore(getDomNode(newChild), getDomNode(refChild)); } @Override public Node replaceChild(Node newChild, Node oldChild) throws DOMException { return document.replaceChild(getDomNode(newChild), getDomNode(oldChild)); } @Override public Node removeChild(Node oldChild) throws DOMException { return document.removeChild(getDomNode(oldChild)); } @Override public Node appendChild(Node newChild) throws DOMException { return document.appendChild(getDomNode(newChild)); } @Override public boolean hasChildNodes() { return document.hasChildNodes(); } @Override public Node cloneNode(boolean deep) { Node node = document.cloneNode(deep); registerChildNodes(node, deep); return findIfPresent(node); } @Override public void normalize() { document.normalize(); } @Override public boolean isSupported(String feature, String version) { return document.isSupported(feature, version); } @Override public String getNamespaceURI() { return document.getNamespaceURI(); } @Override public String getPrefix() { return document.getPrefix(); } @Override public void setPrefix(String prefix) throws DOMException { document.setPrefix(prefix); } @Override public String getLocalName() { return document.getLocalName(); } @Override public boolean hasAttributes() { return document.hasAttributes(); } @Override public String getBaseURI() { return document.getBaseURI(); } @Override public short compareDocumentPosition(Node other) throws DOMException { return document.compareDocumentPosition(getDomNode(other)); } @Override public String getTextContent() throws DOMException { return document.getTextContent(); } @Override public void setTextContent(String textContent) throws DOMException { document.setTextContent(textContent); } @Override public boolean isSameNode(Node other) { return document.isSameNode(getDomNode(other)); } @Override public String lookupPrefix(String namespaceURI) { return document.lookupPrefix(namespaceURI); } @Override public boolean isDefaultNamespace(String namespaceURI) { return document.isDefaultNamespace(namespaceURI); } @Override public String lookupNamespaceURI(String prefix) { return document.lookupNamespaceURI(prefix); } @Override public boolean isEqualNode(Node arg) { return document.isEqualNode(getDomNode(arg)); } @Override public Object getFeature(String feature, String version) { return document.getFeature(feature, version); } @Override public Object setUserData(String key, Object data, UserDataHandler handler) { return document.setUserData(key, data, handler); } @Override public Object getUserData(String key) { return document.getUserData(key); } public Document getDomDocument() { return document; }
Insert a mapping information for Node - Node. In SAAJ, elements in DOM are expected to be interfaces of SAAJ, on the other hand in JDKs Xerces, they are casted to internal impl classes. After removal of SAAJ dependency to JDKs internal classes elements in DOM can never be both of them.
Params:
  • node – SAAJ wrapper node for w3c DOM node
/** * Insert a mapping information for {@link org.w3c.dom.Node} - {@link javax.xml.soap.Node}. * * In SAAJ, elements in DOM are expected to be interfaces of SAAJ, on the other hand in JDKs Xerces, * they are casted to internal impl classes. After removal of SAAJ dependency * to JDKs internal classes elements in DOM can never be both of them. * * @param node SAAJ wrapper node for w3c DOM node */
public void register(javax.xml.soap.Node node) { final Node domElement = getDomNode(node); if (domElement.getUserData(SAAJ_NODE) != null) { throw new IllegalStateException("Element " + domElement.getNodeName() + " is already registered"); } domElement.setUserData(SAAJ_NODE, node, null); } /** * Find a soap wrapper for w3c dom node. * * @param node w3c dom node nullable * @return soap wrapper for w3c dom node * * @throws */ public javax.xml.soap.Node find(Node node) { return find(node, true); } private javax.xml.soap.Node find(Node node, boolean required) { if (node == null) { return null; } if (node instanceof javax.xml.soap.Node) { return (javax.xml.soap.Node) node; } final javax.xml.soap.Node found = (javax.xml.soap.Node) node.getUserData(SAAJ_NODE); if (found == null && required) { throw new IllegalArgumentException(MessageFormat.format("Cannot find SOAP wrapper for element {0}", node)); } return found; }
If corresponding soap wrapper exists for w3c dom node it is returned, if not passed dom element is returned.
Params:
  • node – w3c dom node
Returns:soap wrapper or passed w3c dom node if not found
/** * If corresponding soap wrapper exists for w3c dom node it is returned, * if not passed dom element is returned. * * @param node w3c dom node * @return soap wrapper or passed w3c dom node if not found */
public Node findIfPresent(Node node) { final javax.xml.soap.Node found = find(node, false); return found != null ? found : node; }
Extracts w3c dom node from corresponding soap wrapper.
Params:
  • node – soap or dom nullable
Returns:dom node
/** * Extracts w3c dom node from corresponding soap wrapper. * * @param node soap or dom nullable * @return dom node */
public Node getDomNode(Node node) { if (node instanceof SOAPDocumentImpl) { return ((SOAPDocumentImpl)node).getDomElement(); } else if (node instanceof ElementImpl) { return ((ElementImpl) node).getDomElement(); } else if (node instanceof SOAPTextImpl) { return ((SOAPTextImpl)node).getDomElement(); } else if (node instanceof SOAPCommentImpl) { return ((SOAPCommentImpl)node).getDomElement(); } else if (node instanceof CDATAImpl) { return ((CDATAImpl) node).getDomElement(); } return node; } private Node createSoapNode(Class nodeType, Node node) { if (SOAPTextImpl.class.isAssignableFrom(nodeType)) { return new SOAPTextImpl(this, (Text) node); } else if (SOAPCommentImpl.class.isAssignableFrom(nodeType)) { return new SOAPCommentImpl(this, (Comment) node); } else if (CDATAImpl.class.isAssignableFrom(nodeType)) { return new CDATAImpl(this, (CDATASection) node); } try { Constructor<Node> constructor = nodeType.getConstructor(SOAPDocumentImpl.class, Element.class); return constructor.newInstance(this, node); } catch (Exception e) { throw new IllegalStateException(e); } } public Document getDomElement() { return document; } @Override public String getValue() { throw new UnsupportedOperationException(); } @Override public void setValue(String value) { throw new UnsupportedOperationException(); } @Override public void setParentElement(SOAPElement parent) throws SOAPException { throw new UnsupportedOperationException(); } @Override public SOAPElement getParentElement() { throw new UnsupportedOperationException(); } @Override public void detachNode() { throw new UnsupportedOperationException(); } @Override public void recycleNode() { throw new UnsupportedOperationException(); } }