org.eclipse.persistence.platform.xml.jaxp.JAXPPlatform Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.persistence.core Show documentation
Show all versions of org.eclipse.persistence.core Show documentation
EclipseLink build based upon Git transaction ecdf3c32c4
/*
* Copyright (c) 1998, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.platform.xml.jaxp;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathException;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.eclipse.persistence.internal.helper.XMLHelper;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.platform.xml.XMLNamespaceResolver;
import org.eclipse.persistence.platform.xml.XMLParser;
import org.eclipse.persistence.platform.xml.XMLPlatform;
import org.eclipse.persistence.platform.xml.XMLPlatformException;
import org.eclipse.persistence.platform.xml.XMLPlatformFactory;
import org.eclipse.persistence.platform.xml.XMLTransformer;
import org.w3c.dom.Attr;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
/**
* Purpose: An implementation of XMLPlatform using JAXP 1.3 APIs.
*/
public class JAXPPlatform implements XMLPlatform {
private XPathFactory xPathFactory;
private SchemaFactory schemaFactory;
private DocumentBuilderFactory documentBuilderFactory;
private boolean disableSecureProcessing = false;
public JAXPPlatform() {
super();
}
private DocumentBuilderFactory getDocumentBuilderFactory() {
if(null == documentBuilderFactory) {
documentBuilderFactory = XMLHelper.createDocumentBuilderFactory(isSecureProcessingDisabled());
}
return documentBuilderFactory;
}
public XPathFactory getXPathFactory() {
if(null == xPathFactory) {
xPathFactory = XMLHelper.createXPathFactory(isSecureProcessingDisabled());
}
return xPathFactory;
}
public SchemaFactory getSchemaFactory() {
if(null == schemaFactory) {
schemaFactory = XMLHelper.createSchemaFactory(XMLConstants.W3C_XML_SCHEMA_NS_URI, isSecureProcessingDisabled());
}
return schemaFactory;
}
/**
* Execute advanced XPath statements that are required for TopLink EIS.
* @param contextNode the node relative to which the XPath
* statement will be executed.
* xPath the XPath statement
* namespaceResolver used to resolve namespace prefixes
* to the corresponding namespace URI
* @return the XPath result
* @throws XMLPlatformException
*/
@Override
public NodeList selectNodesAdvanced(Node contextNode, String xPathString, XMLNamespaceResolver xmlNamespaceResolver) throws XMLPlatformException {
try {
XPath xPath = getXPathFactory().newXPath();
if(null != xmlNamespaceResolver) {
JAXPNamespaceContext namespaceContext = new JAXPNamespaceContext(xmlNamespaceResolver);
xPath.setNamespaceContext(namespaceContext);
}
XPathExpression xPathExpression = xPath.compile(xPathString);
return (NodeList) xPathExpression.evaluate(contextNode, XPathConstants.NODESET);
} catch(XPathException e) {
throw XMLPlatformException.xmlPlatformInvalidXPath(e);
}
}
/**
* Execute advanced XPath statements that are required for TopLink EIS.
* @param contextNode
* @param xPathString
* @param xmlNamespaceResolver
* @return
* @throws XMLPlatformException
*/
@Override
public Node selectSingleNodeAdvanced(Node contextNode, String xPathString, XMLNamespaceResolver xmlNamespaceResolver) throws XMLPlatformException {
try {
XPath xPath = getXPathFactory().newXPath();
if(null != xmlNamespaceResolver) {
JAXPNamespaceContext namespaceContext = new JAXPNamespaceContext(xmlNamespaceResolver);
xPath.setNamespaceContext(namespaceContext);
}
XPathExpression xPathExpression = xPath.compile(xPathString);
return (Node) xPathExpression.evaluate(contextNode, XPathConstants.NODE);
} catch(XPathException e) {
throw XMLPlatformException.xmlPlatformInvalidXPath(e);
}
}
@Override
public boolean isWhitespaceNode(Text text) {
String value = text.getNodeValue();
if (null == value) {
return false;
} else {
return value.trim().equals("");
}
}
@Override
public XMLParser newXMLParser() {
return new JAXPParser();
}
@Override
public XMLParser newXMLParser(Map parserFeatures) {
return new JAXPParser(parserFeatures);
}
@Override
public XMLTransformer newXMLTransformer() {
return new JAXPTransformer();
}
@Override
public Document createDocument() throws XMLPlatformException {
try {
DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder();
return documentBuilder.newDocument();
} catch (Exception e) {
throw XMLPlatformException.xmlPlatformCouldNotCreateDocument(e);
}
}
@Override
public Document createDocumentWithPublicIdentifier(String name, String publicIdentifier, String systemIdentifier) throws XMLPlatformException {
try {
if (null == publicIdentifier) {
return createDocumentWithSystemIdentifier(name, systemIdentifier);
}
DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder();
DOMImplementation domImpl = documentBuilder.getDOMImplementation();
DocumentType docType = domImpl.createDocumentType(name, publicIdentifier, systemIdentifier);
Document document = domImpl.createDocument(null, name, docType);
return document;
} catch (Exception e) {
throw XMLPlatformException.xmlPlatformCouldNotCreateDocument(e);
}
}
@Override
public Document createDocumentWithSystemIdentifier(String name, String systemIdentifier) throws XMLPlatformException {
try {
Document document = null;
if (null == systemIdentifier) {
document = createDocument();
Element rootElement = document.createElement(name);
document.appendChild(rootElement);
return document;
}
DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder();
DOMImplementation domImpl = documentBuilder.getDOMImplementation();
DocumentType docType = domImpl.createDocumentType(name, null, systemIdentifier);
document = domImpl.createDocument(null, name, docType);
return document;
} catch (Exception e) {
throw XMLPlatformException.xmlPlatformCouldNotCreateDocument(e);
}
}
@Override
public String resolveNamespacePrefix(Node contextNode, String namespacePrefix) throws XMLPlatformException {
if (null == namespacePrefix) {
if (null == contextNode.getPrefix()) {
return contextNode.getNamespaceURI();
}
} else if (namespacePrefix.equals(contextNode.getPrefix())) {
return contextNode.getNamespaceURI();
}
if (contextNode.getNodeType() == Node.ELEMENT_NODE) {
Element contextElement = (Element)contextNode;
Attr namespaceDeclaration = null;
if(namespacePrefix != null) {
namespaceDeclaration = contextElement.getAttributeNode("xmlns:" + namespacePrefix);
} else {
//look for default namespace declaration for null prefix
namespaceDeclaration = contextElement.getAttributeNode(javax.xml.XMLConstants.XMLNS_ATTRIBUTE);
}
if (null != namespaceDeclaration) {
return namespaceDeclaration.getValue();
}
}
Node parentNode = contextNode.getParentNode();
if (parentNode!=null && parentNode.getNodeType() == Node.ELEMENT_NODE) {
return resolveNamespacePrefix(parentNode, namespacePrefix);
}
return null;
}
@Override
public boolean validateDocument(Document document, URL xmlSchemaURL, ErrorHandler errorHandler) throws XMLPlatformException {
Schema xmlSchema;
try {
xmlSchema = getSchemaFactory().newSchema(xmlSchemaURL);
} catch(SAXException e) {
throw XMLPlatformException.xmlPlatformErrorResolvingXMLSchema(xmlSchemaURL, e);
}
try {
Validator validator = xmlSchema.newValidator();
validator.setErrorHandler(errorHandler);
validator.validate(new DOMSource(document));
} catch(Exception e) {
throw XMLPlatformException.xmlPlatformValidationException(e);
}
return true;
}
@Override
public boolean validate(Element elem, org.eclipse.persistence.oxm.XMLDescriptor xmlDescriptor, ErrorHandler handler) throws XMLPlatformException {
return true;
}
@Override
public void namespaceQualifyFragment(Element next) {
namespaceQualifyFragment(next, new ArrayList());
}
//pass list of prefixes declared and encountered
private void namespaceQualifyFragment(Element next, List declaredPrefixes) {
String elementUri = next.getNamespaceURI();
String elementPrefix = next.getPrefix();
if (elementPrefix != null) {
//see if this prefix is already declared if yes - do nothing, if no declare
Attr namespaceDeclaration = next.getAttributeNode(javax.xml.XMLConstants.XMLNS_ATTRIBUTE+":" + elementPrefix);
if ((null == namespaceDeclaration) && !declaredPrefixes.contains(elementPrefix)) {
(next).setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE+ ":" + elementPrefix, elementUri);
declaredPrefixes.add(elementPrefix);
}
}
//check all attributes prefixes and if any of them arent declared add them also.
NamedNodeMap attributes = next.getAttributes();
int attributesSize = attributes.getLength();
for (int i = 0; i < attributesSize; i++) {
Attr nextAttribute = (Attr)attributes.item(i);
String attributePrefix = nextAttribute.getPrefix();
if (attributePrefix != null) {
//if attribute is a namespace declaration add to declared list
if (javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(nextAttribute.getNamespaceURI())) {
declaredPrefixes.add(nextAttribute.getLocalName());
} else {
Attr namespaceDeclaration = next.getAttributeNode(javax.xml.XMLConstants.XMLNS_ATTRIBUTE +":" + attributePrefix);
if ((null == namespaceDeclaration) && !declaredPrefixes.contains(attributePrefix)) {
String attributeUri = nextAttribute.getNamespaceURI();
(next).setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + ":" + attributePrefix, attributeUri);
declaredPrefixes.add(attributePrefix);
}
//if xsi:type declaration deal with that value
if (javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI.equals(nextAttribute.getNamespaceURI()) && Constants.SCHEMA_TYPE_ATTRIBUTE.equals(nextAttribute.getLocalName())) {
String value = nextAttribute.getValue();
int colonIndex = value.indexOf(':');
if (colonIndex > -1) {
String prefix = value.substring(0, colonIndex);
namespaceDeclaration = next.getAttributeNode(javax.xml.XMLConstants.XMLNS_ATTRIBUTE +":" + prefix);
if ((null == namespaceDeclaration) && !declaredPrefixes.contains(prefix)) {
String uri = XMLPlatformFactory.getInstance().getXMLPlatform().resolveNamespacePrefix(next, prefix);
(next).setAttributeNS(javax.xml.XMLConstants.XMLNS_ATTRIBUTE_NS_URI, javax.xml.XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix, uri);
declaredPrefixes.add(prefix);
}
}
}
}
}
}
NodeList children = next.getChildNodes();
int numberOfNodes = children.getLength();
for (int i = 0; i < numberOfNodes; i++) {
Node nextNode = children.item(i);
if (nextNode.getNodeType() == Node.ELEMENT_NODE) {
Element child = (Element)nextNode;
namespaceQualifyFragment(child, declaredPrefixes);
}
}
}
@Override
public void setDisableSecureProcessing(boolean disableSecureProcessing) {
boolean shouldReset = this.disableSecureProcessing ^ disableSecureProcessing;
this.disableSecureProcessing = disableSecureProcessing;
if (shouldReset) {
documentBuilderFactory = null;
schemaFactory = null;
xPathFactory = null;
}
}
@Override
public boolean isSecureProcessingDisabled() {
return disableSecureProcessing;
}
}