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 eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction 180e602
/*******************************************************************************
* Copyright (c) 1998, 2014 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 v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* 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.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.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;
public JAXPPlatform() {
super();
}
private DocumentBuilderFactory getDocumentBuilderFactory() {
if(null == documentBuilderFactory) {
documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
}
return documentBuilderFactory;
}
public XPathFactory getXPathFactory() {
if(null == xPathFactory) {
xPathFactory = XPathFactory.newInstance();
}
return xPathFactory;
}
public SchemaFactory getSchemaFactory() {
if(null == schemaFactory) {
schemaFactory = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI);
}
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
*/
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
*/
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);
}
}
public boolean isWhitespaceNode(Text text) {
String value = text.getNodeValue();
if (null == value) {
return false;
} else {
return value.trim().equals("");
}
}
public XMLParser newXMLParser() {
return new JAXPParser();
}
public XMLParser newXMLParser(Map parserFeatures) {
return new JAXPParser(parserFeatures);
}
public XMLTransformer newXMLTransformer() {
return new JAXPTransformer();
}
public Document createDocument() throws XMLPlatformException {
try {
DocumentBuilder documentBuilder = getDocumentBuilderFactory().newDocumentBuilder();
return documentBuilder.newDocument();
} catch (Exception e) {
throw XMLPlatformException.xmlPlatformCouldNotCreateDocument(e);
}
}
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);
}
}
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);
}
}
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;
}
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;
}
public boolean validate(Element elem, org.eclipse.persistence.oxm.XMLDescriptor xmlDescriptor, ErrorHandler handler) throws XMLPlatformException {
return true;
}
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);
}
}
}
}