|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package com.sun.org.apache.xpath.internal.jaxp; |
|
|
|
import com.sun.org.apache.xalan.internal.res.XSLMessages; |
|
import com.sun.org.apache.xml.internal.dtm.DTM; |
|
import com.sun.org.apache.xpath.internal.axes.LocPathIterator; |
|
import com.sun.org.apache.xpath.internal.objects.XObject; |
|
import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; |
|
import java.io.IOException; |
|
import javax.xml.namespace.QName; |
|
import javax.xml.parsers.DocumentBuilderFactory; |
|
import javax.xml.parsers.ParserConfigurationException; |
|
import javax.xml.transform.TransformerException; |
|
import javax.xml.xpath.XPathConstants; |
|
import javax.xml.xpath.XPathEvaluationResult; |
|
import javax.xml.xpath.XPathExpressionException; |
|
import javax.xml.xpath.XPathFunctionResolver; |
|
import javax.xml.xpath.XPathNodes; |
|
import javax.xml.xpath.XPathVariableResolver; |
|
import jdk.xml.internal.JdkXmlFeatures; |
|
import jdk.xml.internal.JdkXmlUtils; |
|
import org.w3c.dom.Document; |
|
import org.w3c.dom.Node; |
|
import org.w3c.dom.traversal.NodeIterator; |
|
import org.xml.sax.InputSource; |
|
import org.xml.sax.SAXException; |
|
|
|
|
|
|
|
|
|
*/ |
|
class XPathImplUtil { |
|
XPathFunctionResolver functionResolver; |
|
XPathVariableResolver variableResolver; |
|
JAXPPrefixResolver prefixResolver; |
|
boolean overrideDefaultParser; |
|
// By default Extension Functions are allowed in XPath Expressions. If |
|
// Secure Processing Feature is set on XPathFactory then the invocation of |
|
|
|
boolean featureSecureProcessing = false; |
|
JdkXmlFeatures featureManager; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
XObject eval(Object contextItem, com.sun.org.apache.xpath.internal.XPath xpath) |
|
throws javax.xml.transform.TransformerException { |
|
com.sun.org.apache.xpath.internal.XPathContext xpathSupport; |
|
if (contextItem == null && xpath.getExpression() instanceof LocPathIterator) { |
|
|
|
throw new TransformerException(XSLMessages.createXPATHMessage( |
|
XPATHErrorResources.ER_CONTEXT_CAN_NOT_BE_NULL, |
|
new Object[] {})); |
|
} |
|
if (functionResolver != null) { |
|
JAXPExtensionsProvider jep = new JAXPExtensionsProvider( |
|
functionResolver, featureSecureProcessing, featureManager); |
|
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(jep); |
|
} else { |
|
xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(); |
|
} |
|
|
|
xpathSupport.setVarStack(new JAXPVariableStack(variableResolver)); |
|
XObject xobj; |
|
|
|
Node contextNode = (Node)contextItem; |
|
// We always need to have a ContextNode with Xalan XPath implementation |
|
// To allow simple expression evaluation like 1+1 we are setting |
|
|
|
if (contextNode == null) { |
|
xobj = xpath.execute(xpathSupport, DTM.NULL, prefixResolver); |
|
} else { |
|
xobj = xpath.execute(xpathSupport, contextNode, prefixResolver); |
|
} |
|
|
|
return xobj; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Document getDocument(InputSource source) |
|
throws XPathExpressionException { |
|
requireNonNull(source, "Source"); |
|
try { |
|
// we'd really like to cache those DocumentBuilders, but we can't because: |
|
// 1. thread safety. parsers are not thread-safe, so at least |
|
// we need one instance per a thread. |
|
// 2. parsers are non-reentrant, so now we are looking at having a |
|
// pool of parsers. |
|
// 3. then the class loading issue. The look-up procedure of |
|
// DocumentBuilderFactory.newInstance() depends on context class loader |
|
// and system properties, which may change during the execution of JVM. |
|
// |
|
// so we really have to create a fresh DocumentBuilder every time we need one |
|
|
|
DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser); |
|
return dbf.newDocumentBuilder().parse(source); |
|
} catch (ParserConfigurationException | SAXException | IOException e) { |
|
throw new XPathExpressionException (e); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Object getResultAsType(XObject resultObject, QName returnType) |
|
throws TransformerException { |
|
|
|
if (returnType.equals(XPathConstants.STRING)) { |
|
return resultObject.str(); |
|
} |
|
|
|
if (returnType.equals(XPathConstants.NUMBER)) { |
|
return resultObject.num(); |
|
} |
|
|
|
if (returnType.equals(XPathConstants.BOOLEAN)) { |
|
return resultObject.bool(); |
|
} |
|
|
|
if (returnType.equals(XPathConstants.NODESET)) { |
|
return resultObject.nodelist(); |
|
} |
|
|
|
if (returnType.equals(XPathConstants.NODE)) { |
|
NodeIterator ni = resultObject.nodeset(); |
|
|
|
return ni.nextNode(); |
|
} |
|
// If isSupported check is already done then the execution path |
|
|
|
String fmsg = XSLMessages.createXPATHMessage( |
|
XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, |
|
new Object[] { returnType.toString()}); |
|
throw new IllegalArgumentException (fmsg); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
<T> T getXPathResult(XObject resultObject, Class<T> type) |
|
throws TransformerException { |
|
int resultType = resultObject.getType(); |
|
|
|
switch (resultType) { |
|
case XObject.CLASS_BOOLEAN : |
|
return type.cast(new XPathResultImpl<>(resultObject, Boolean.class)); |
|
case XObject.CLASS_NUMBER : |
|
return type.cast(new XPathResultImpl<>(resultObject, Double.class)); |
|
case XObject.CLASS_STRING : |
|
return type.cast(new XPathResultImpl<>(resultObject, String.class)); |
|
case XObject.CLASS_NODESET : |
|
return type.cast(new XPathResultImpl<>(resultObject, XPathNodes.class)); |
|
case XObject.CLASS_RTREEFRAG : |
|
return type.cast(new XPathResultImpl<>(resultObject, Node.class)); |
|
} |
|
|
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
<T> void isSupportedClassType(Class<T> type) { |
|
requireNonNull(type, "The class type"); |
|
if (type.isAssignableFrom(Boolean.class) || |
|
type.isAssignableFrom(Double.class) || |
|
type.isAssignableFrom(Integer.class) || |
|
type.isAssignableFrom(Long.class) || |
|
type.isAssignableFrom(String.class) || |
|
type.isAssignableFrom(XPathNodes.class) || |
|
type.isAssignableFrom(Node.class) || |
|
type.isAssignableFrom(XPathEvaluationResult.class)) { |
|
return; |
|
} |
|
String fmsg = XSLMessages.createXPATHMessage( |
|
XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, |
|
new Object[] { type.toString() }); |
|
throw new IllegalArgumentException (fmsg); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
void isSupported(QName returnType) { |
|
requireNonNull(returnType, "returnType"); |
|
if (returnType.equals(XPathConstants.STRING) || |
|
returnType.equals(XPathConstants.NUMBER) || |
|
returnType.equals(XPathConstants.BOOLEAN) || |
|
returnType.equals(XPathConstants.NODE) || |
|
returnType.equals(XPathConstants.NODESET)) { |
|
return; |
|
} |
|
String fmsg = XSLMessages.createXPATHMessage( |
|
XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, |
|
new Object[] { returnType.toString() }); |
|
throw new IllegalArgumentException (fmsg); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
<T> void requireNonNull(T param, String paramName) { |
|
if (param == null) { |
|
String fmsg = XSLMessages.createXPATHMessage( |
|
XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, |
|
new Object[] {paramName}); |
|
throw new NullPointerException (fmsg); |
|
} |
|
} |
|
} |