|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.org.apache.xml.internal.security.utils; |
|
|
|
import java.lang.reflect.Constructor; |
|
import java.lang.reflect.Method; |
|
import java.lang.reflect.Modifier; |
|
|
|
import javax.xml.transform.ErrorListener; |
|
import javax.xml.transform.SourceLocator; |
|
import javax.xml.transform.TransformerException; |
|
|
|
import com.sun.org.apache.xml.internal.security.transforms.implementations.FuncHere; |
|
import com.sun.org.apache.xml.internal.utils.PrefixResolver; |
|
import com.sun.org.apache.xml.internal.utils.PrefixResolverDefault; |
|
import com.sun.org.apache.xpath.internal.Expression; |
|
import com.sun.org.apache.xpath.internal.XPath; |
|
import com.sun.org.apache.xpath.internal.XPathContext; |
|
import com.sun.org.apache.xpath.internal.compiler.FunctionTable; |
|
import com.sun.org.apache.xpath.internal.objects.XObject; |
|
import org.w3c.dom.Document; |
|
import org.w3c.dom.Node; |
|
import org.w3c.dom.NodeList; |
|
|
|
|
|
|
|
|
|
*/ |
|
class XalanXPathAPI implements XPathAPI { |
|
|
|
private static final com.sun.org.slf4j.internal.Logger LOG = |
|
com.sun.org.slf4j.internal.LoggerFactory.getLogger(XalanXPathAPI.class); |
|
|
|
private String xpathStr; |
|
|
|
private XPath xpath; |
|
|
|
private static FunctionTable funcTable; |
|
|
|
private static boolean installed; |
|
|
|
private XPathContext context; |
|
|
|
static { |
|
fixupFunctionTable(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public NodeList selectNodeList( |
|
Node contextNode, Node xpathnode, String str, Node namespaceNode |
|
) throws TransformerException { |
|
|
|
|
|
XObject list = eval(contextNode, xpathnode, str, namespaceNode); |
|
|
|
|
|
return list.nodelist(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public boolean evaluate(Node contextNode, Node xpathnode, String str, Node namespaceNode) |
|
throws TransformerException { |
|
XObject object = eval(contextNode, xpathnode, str, namespaceNode); |
|
return object.bool(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public void clear() { |
|
xpathStr = null; |
|
xpath = null; |
|
context = null; |
|
} |
|
|
|
public static boolean isInstalled() { |
|
return installed; |
|
} |
|
|
|
private XObject eval(Node contextNode, Node xpathnode, String str, Node namespaceNode) |
|
throws TransformerException { |
|
if (context == null) { |
|
context = new XPathContext(xpathnode); |
|
context.setSecureProcessing(true); |
|
} |
|
|
|
// Create an object to resolve namespace prefixes. |
|
// XPath namespaces are resolved from the input context node's document element |
|
// if it is a root node, or else the current context node (for lack of a better |
|
|
|
Node resolverNode = |
|
(namespaceNode.getNodeType() == Node.DOCUMENT_NODE) |
|
? ((Document) namespaceNode).getDocumentElement() : namespaceNode; |
|
PrefixResolverDefault prefixResolver = new PrefixResolverDefault(resolverNode); |
|
|
|
if (!str.equals(xpathStr)) { |
|
if (str.indexOf("here()") > 0) { |
|
context.reset(); |
|
} |
|
xpath = createXPath(str, prefixResolver); |
|
xpathStr = str; |
|
} |
|
|
|
|
|
int ctxtNode = context.getDTMHandleFromNode(contextNode); |
|
|
|
return xpath.execute(context, ctxtNode, prefixResolver); |
|
} |
|
|
|
private XPath createXPath(String str, PrefixResolver prefixResolver) throws TransformerException { |
|
XPath xpath = null; |
|
Class<?>[] classes = new Class<?>[]{String.class, SourceLocator.class, PrefixResolver.class, int.class, |
|
ErrorListener.class, FunctionTable.class}; |
|
Object[] objects = |
|
new Object[]{str, null, prefixResolver, XPath.SELECT, null, funcTable}; |
|
try { |
|
Constructor<?> constructor = XPath.class.getConstructor(classes); |
|
xpath = (XPath) constructor.newInstance(objects); |
|
} catch (Exception ex) { |
|
LOG.debug(ex.getMessage(), ex); |
|
} |
|
if (xpath == null) { |
|
xpath = new XPath(str, null, prefixResolver, XPath.SELECT, null); |
|
} |
|
return xpath; |
|
} |
|
|
|
private static synchronized void fixupFunctionTable() { |
|
installed = false; |
|
if (new FunctionTable().functionAvailable("here")) { |
|
LOG.debug("Here function already registered"); |
|
installed = true; |
|
return; |
|
} |
|
LOG.debug("Registering Here function"); |
|
|
|
|
|
*/ |
|
try { |
|
Class<?>[] args = {String.class, Expression.class}; |
|
Method installFunction = FunctionTable.class.getMethod("installFunction", args); |
|
if ((installFunction.getModifiers() & Modifier.STATIC) != 0) { |
|
Object[] params = {"here", new FuncHere()}; |
|
installFunction.invoke(null, params); |
|
installed = true; |
|
} |
|
} catch (Exception ex) { |
|
LOG.debug("Error installing function using the static installFunction method", ex); |
|
} |
|
if (!installed) { |
|
try { |
|
funcTable = new FunctionTable(); |
|
Class<?>[] args = {String.class, Class.class}; |
|
Method installFunction = FunctionTable.class.getMethod("installFunction", args); |
|
Object[] params = {"here", FuncHere.class}; |
|
installFunction.invoke(funcTable, params); |
|
installed = true; |
|
} catch (Exception ex) { |
|
LOG.debug("Error installing function using the static installFunction method", ex); |
|
} |
|
} |
|
if (installed) { |
|
LOG.debug("Registered class {} for XPath function 'here()' function in internal table", FuncHere.class.getName()); |
|
} else { |
|
LOG.debug("Unable to register class {} for XPath function 'here()' function in internal table", FuncHere.class.getName()); |
|
} |
|
} |
|
|
|
} |