summaryrefslogtreecommitdiff
path: root/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java')
-rw-r--r--eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java523
1 files changed, 523 insertions, 0 deletions
diff --git a/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java
new file mode 100644
index 00000000..7df242bd
--- /dev/null
+++ b/eaaf_core/src/main/java/at/gv/egiz/eaaf/core/impl/utils/XPathUtils.java
@@ -0,0 +1,523 @@
+/*******************************************************************************
+ *******************************************************************************/
+
+
+package at.gv.egiz.eaaf.core.impl.utils;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jaxen.JaxenException;
+import org.jaxen.NamespaceContext;
+import org.jaxen.Navigator;
+import org.jaxen.SimpleNamespaceContext;
+import org.jaxen.dom.DOMXPath;
+import org.jaxen.dom.DocumentNavigator;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.traversal.NodeIterator;
+
+import at.gv.egiz.eaaf.core.api.data.XMLNamespaceConstants;
+import at.gv.egiz.eaaf.core.exceptions.XPathException;
+
+/**
+ * Utility methods to evaluate XPath expressions on DOM nodes.
+ *
+ * @author Patrick Peck
+ * @version $Id$
+ */
+public class XPathUtils {
+
+ /**
+ * The XPath expression selecting all nodes under a given root (including the
+ * root node itself).
+ */
+ public static final String ALL_NODES_XPATH =
+ "(.//. | .//@* | .//namespace::*)";
+
+ /** The <code>DocumentNavigator</code> to use for navigating the document. */
+ private static Navigator documentNavigator =
+ DocumentNavigator.getInstance();
+ /** The default namespace prefix to namespace URI mappings. */
+ private static NamespaceContext NS_CONTEXT;
+
+ static {
+ SimpleNamespaceContext ctx = new SimpleNamespaceContext();
+ ctx.addNamespace(XMLNamespaceConstants.MOA_PREFIX, XMLNamespaceConstants.MOA_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.MOA_CONFIG_PREFIX, XMLNamespaceConstants.MOA_CONFIG_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.MOA_ID_CONFIG_PREFIX, XMLNamespaceConstants.MOA_ID_CONFIG_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.SL10_PREFIX, XMLNamespaceConstants.SL10_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.SL11_PREFIX, XMLNamespaceConstants.SL11_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.SL12_PREFIX, XMLNamespaceConstants.SL12_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.ECDSA_PREFIX, XMLNamespaceConstants.ECDSA_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.PD_PREFIX, XMLNamespaceConstants.PD_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.SAML_PREFIX, XMLNamespaceConstants.SAML_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.SAMLP_PREFIX, XMLNamespaceConstants.SAMLP_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.DSIG_PREFIX, XMLNamespaceConstants.DSIG_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.XSLT_PREFIX, XMLNamespaceConstants.XSLT_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.XSI_PREFIX, XMLNamespaceConstants.XSI_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.DSIG_FILTER2_PREFIX, XMLNamespaceConstants.DSIG_FILTER2_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.DSIG_EC_PREFIX, XMLNamespaceConstants.DSIG_EC_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.MD_PREFIX, XMLNamespaceConstants.MD_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.MDP_PREFIX, XMLNamespaceConstants.MDP_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.MVV_PREFIX, XMLNamespaceConstants.MVV_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.STB_PREFIX, XMLNamespaceConstants.STB_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.WRR_PREFIX, XMLNamespaceConstants.WRR_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.STORK_PREFIX, XMLNamespaceConstants.STORK_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.STORKP_PREFIX, XMLNamespaceConstants.STORKP_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.SAML2_PREFIX, XMLNamespaceConstants.SAML2_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.SAML2P_PREFIX, XMLNamespaceConstants.SAML2P_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.XENC_PREFIX, XMLNamespaceConstants.XENC_NS_URI);
+ ctx.addNamespace(XMLNamespaceConstants.XADES_1_1_1_NS_PREFIX, XMLNamespaceConstants.XADES_1_1_1_NS_URI);
+ NS_CONTEXT = ctx;
+ }
+
+ /**
+ * Return a <code>NodeIterator</code> over the nodes matching the XPath
+ * expression.
+ *
+ * All namespace URIs and prefixes declared in the <code>Constants</code>
+ * interface are used for resolving namespaces.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param exp The XPath expression to evaluate.
+ * @return An iterator over the resulting nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static NodeIterator selectNodeIterator(Node contextNode, String exp)
+ throws XPathException {
+
+ return selectNodeIterator(contextNode, NS_CONTEXT, exp);
+ }
+
+ /**
+ * Return a <code>NodeIterator</code> over the nodes matching the XPath
+ * expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param namespaceElement An element from which to build the
+ * namespace mapping for evaluating the XPath expression
+ * @param exp The XPath expression to evaluate.
+ * @return An iterator over the resulting nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static NodeIterator selectNodeIterator(
+ Node contextNode,
+ Element namespaceElement,
+ String exp)
+ throws XPathException {
+
+ try {
+ SimpleNamespaceContext ctx = new SimpleNamespaceContext();
+ ctx.addElementNamespaces(documentNavigator, namespaceElement);
+ return selectNodeIterator(contextNode, ctx, exp);
+
+ } catch (JaxenException e) {
+ throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ /**
+ * Return a <code>NodeIterator</code> over the nodes matching the XPath
+ * expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param namespaceMapping A namespace prefix to namespace URI mapping
+ * (<code>String</code> to <code>String</code>) for evaluating the XPath
+ * expression.
+ * @param exp The XPath expression to evaluate.
+ * @return An iterator over the resulting nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static NodeIterator selectNodeIterator(
+ Node contextNode,
+ Map namespaceMapping,
+ String exp)
+ throws XPathException {
+
+ SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping);
+
+ return selectNodeIterator(contextNode, ctx, exp);
+ }
+
+ /**
+ * Return a <code>NodeIterator</code> over the nodes matching the XPath
+ * expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param nsContext The <code>NamespaceContext</code> for resolving namespace
+ * prefixes to namespace URIs for evaluating the XPath expression.
+ * @param exp The XPath expression to evaluate.
+ * @return An iterator over the resulting nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ private static NodeIterator selectNodeIterator(
+ Node contextNode,
+ NamespaceContext nsContext,
+ String exp)
+ throws XPathException {
+
+ try {
+ DOMXPath xpath = new DOMXPath(exp);
+ List nodes;
+
+ xpath.setNamespaceContext(nsContext);
+ nodes = xpath.selectNodes(contextNode);
+ return new NodeIteratorAdapter(nodes.listIterator());
+
+ } catch (JaxenException e) {
+ throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ /**
+ * Return a <code>NodeList</code> of all the nodes matching the XPath
+ * expression.
+ *
+ * All namespace URIs and prefixes declared in the <code>Constants</code>
+ * interface are used for resolving namespaces.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param exp The XPath expression to evaluate.
+ * @return A <code>NodeList</code> containing the matching nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static NodeList selectNodeList(Node contextNode, String exp)
+ throws XPathException {
+
+ return selectNodeList(contextNode, NS_CONTEXT, exp);
+ }
+
+ /**
+ * Return a <code>NodeList</code> of all the nodes matching the XPath
+ * expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param namespaceElement An element from which to build the
+ * namespace mapping for evaluating the XPath expression
+ * @param exp The XPath expression to evaluate.
+ * @return A <code>NodeList</code> containing the matching nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static NodeList selectNodeList(
+ Node contextNode,
+ Element namespaceElement,
+ String exp)
+ throws XPathException {
+
+ try {
+ SimpleNamespaceContext ctx = new SimpleNamespaceContext();
+
+ ctx.addElementNamespaces(documentNavigator, namespaceElement);
+ return selectNodeList(contextNode, ctx, exp);
+
+ } catch (JaxenException e) {
+ throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ /**
+ * Return a <code>NodeList</code> of all the nodes matching the XPath
+ * expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param namespaceMapping A namespace prefix to namespace URI mapping
+ * (<code>String</code> to <code>String</code>) for evaluating the XPath
+ * expression.
+ * @param exp The XPath expression to evaluate.
+ * @return A <code>NodeList</code> containing the matching nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static NodeList selectNodeList(
+ Node contextNode,
+ Map namespaceMapping,
+ String exp)
+ throws XPathException {
+
+ SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping);
+
+ return selectNodeList(contextNode, ctx, exp);
+ }
+
+ /**
+ * Return a <code>NodeList</code> of all the nodes matching the XPath
+ * expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param nsContext The <code>NamespaceContext</code> for resolving namespace
+ * prefixes to namespace URIs for evaluating the XPath expression.
+ * @param exp The XPath expression to evaluate.
+ * @return A <code>NodeList</code> containing the matching nodes.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ private static NodeList selectNodeList(Node contextNode, NamespaceContext nsContext, String exp) throws XPathException {
+ try {
+ DOMXPath xpath = new DOMXPath(exp);
+ List nodes;
+ xpath.setNamespaceContext(nsContext);
+ nodes = xpath.selectNodes(contextNode);
+ return new NodeListAdapter(nodes);
+
+ } catch (JaxenException e) {
+ throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ /**
+ * Select the first node matching an XPath expression.
+ *
+ * All namespace URIs and prefixes declared in the <code>Constants</code>
+ * interface are used for resolving namespaces.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param exp The XPath expression to evaluate.
+ * @return Node The first node matching the XPath expression, or
+ * <code>null</code>, if no node matched.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static Node selectSingleNode(Node contextNode, String exp)
+ throws XPathException {
+
+ return selectSingleNode(contextNode, NS_CONTEXT, exp);
+ }
+
+ /**
+ * Select the first node matching an XPath expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param namespaceElement An element from which to build the
+ * namespace mapping for evaluating the XPath expression
+ * @param exp The XPath expression to evaluate.
+ * @return Node The first node matching the XPath expression, or
+ * <code>null</code>, if no node matched.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static Node selectSingleNode(
+ Node contextNode,
+ Element namespaceElement,
+ String exp)
+ throws XPathException {
+
+ try {
+ SimpleNamespaceContext ctx = new SimpleNamespaceContext();
+ ctx.addElementNamespaces(documentNavigator, namespaceElement);
+ return selectSingleNode(contextNode, ctx, exp);
+
+ } catch (JaxenException e) {
+ throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ /**
+ * Select the first node matching an XPath expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param namespaceMapping A namespace prefix to namespace URI mapping
+ * (<code>String</code> to <code>String</code>) for evaluating the XPath
+ * expression.
+ * @param exp The XPath expression to evaluate.
+ * @return Node The first node matching the XPath expression, or
+ * <code>null</code>, if no node matched.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static Node selectSingleNode(
+ Node contextNode,
+ Map namespaceMapping,
+ String exp)
+ throws XPathException {
+
+ SimpleNamespaceContext ctx = new SimpleNamespaceContext(namespaceMapping);
+
+ return selectSingleNode(contextNode, ctx, exp);
+ }
+
+ /**
+ * Select the first node matching an XPath expression.
+ *
+ * @param contextNode The root node from which to evaluate the XPath
+ * expression.
+ * @param nsContext The <code>NamespaceContext</code> for resolving namespace
+ * prefixes to namespace URIs for evaluating the XPath expression.
+ * @param exp The XPath expression to evaluate.
+ * @return Node The first node matching the XPath expression, or
+ * <code>null</code>, if no node matched.
+ * @throws XPathException An error occurred evaluating the XPath expression.
+ */
+ public static Node selectSingleNode(
+ Node contextNode,
+ NamespaceContext nsContext,
+ String exp)
+ throws XPathException {
+
+ try {
+ DOMXPath xpath = new DOMXPath(exp);
+ xpath.setNamespaceContext(nsContext);
+ return (Node) xpath.selectSingleNode(contextNode);
+
+ } catch (JaxenException e) {
+ throw new XPathException("XPath operation FAILED. Reason: " + e.getMessage(), e);
+
+ }
+ }
+
+ /**
+ * Return the value of a DOM element whose location is given by an XPath
+ * expression.
+ *
+ * @param root The root element from which to evaluate the XPath.
+ * @param xpath The XPath expression pointing to the element whose value
+ * to return.
+ * @param def The default value to return, if no element can be found using
+ * the given <code>xpath</code>.
+ * @return The element value, if it can be located using the
+ * <code>xpath</code>. Otherwise, <code>def</code> is returned.
+ */
+ public static String getElementValue(
+ Element root,
+ String xpath,
+ String def) {
+
+ Element elem = (Element) XPathUtils.selectSingleNode(root, xpath);
+ return elem != null ? DOMUtils.getText(elem) : def;
+ }
+
+ /**
+ * Return the value of a DOM attribute whose location is given by an XPath
+ * expression.
+ *
+ * @param root The root element from which to evaluate the XPath.
+ * @param xpath The XPath expression pointing to the attribute whose value to
+ * return.
+ * @param def The default value to return, if no attribute can be found using
+ * the given <code>xpath</code>.
+ * @return The element value, if it can be located using the
+ * <code>xpath</code>. Otherwise, <code>def</code> is returned.
+ */
+ public static String getAttributeValue(
+ Element root,
+ String xpath,
+ String def) {
+
+ Attr attr = (Attr) XPathUtils.selectSingleNode(root, xpath);
+ return attr != null ? attr.getValue() : def;
+ }
+
+ /**
+ * Returns the namespace prefix used within <code>XPathUtils</code> for referring to
+ * the namespace of the specified (Security Layer command) element.
+ *
+ * This namespace prefix can be used in various XPath expression evaluation methods
+ * within <code> XPathUtils</code> without explicitely binding it to the particular
+ * namespace.
+ *
+ * @param contextElement The (Security Layer command) element.
+ *
+ * @return the namespace prefix used within <code>XPathUtils</code> for referring to
+ * the namespace of the specified (Security Layer command) element.
+ *
+ * throws XpathException If the specified element has a namespace other than the ones
+ * known by this implementation as valid Security Layer namespaces (cf.
+ * @link Constants#SL10_NS_URI, @link Constants#SL11_NS_URI, @link Constants#SL12_NS_URI).
+ */
+ public static String getSlPrefix (Element contextElement) throws XPathException
+ {
+ String sLNamespace = contextElement.getNamespaceURI();
+ String sLPrefix = null;
+
+ if (sLNamespace.equals(XMLNamespaceConstants.SL10_NS_URI))
+ sLPrefix = XMLNamespaceConstants.SL10_PREFIX;
+
+ else if (sLNamespace.equals(XMLNamespaceConstants.SL12_NS_URI))
+ sLPrefix = XMLNamespaceConstants.SL12_PREFIX;
+
+ else if (sLNamespace.equals(XMLNamespaceConstants.SL11_NS_URI))
+ sLPrefix = XMLNamespaceConstants.SL11_PREFIX;
+
+ else
+ throw new XPathException("XPath operation FAILED. Reason: ");
+
+ return sLPrefix;
+ }
+
+
+ /**
+ * Return the SecurityLayer namespace prefix of the context element.
+ * If the context element is not the element that lies within the
+ * SecurityLayer namespace. The Securitylayer namespace is derived from
+ * the <code>xmlns:sl10</code>, <code>sl11</code> or <code>sl</code>
+ * attribute of the context element.
+ *
+ * The returned prefix is needed for evaluating XPATH expressions.
+ *
+ * @param contextElement The element to get a prefix for the Securitylayer namespace,
+ * that is used within the corresponding document.
+ *
+ * @return The string <code>sl10</code>, <code>sl11</code> or <code>sl</code>,
+ * depending on the SecurityLayer namespace of the contextElement.
+ *
+ * throws XPathException If no (vlalid) SecurityLayer namespace prefix or namespace
+ * is defined.
+ */
+ public static String getSlPrefixFromNoRoot (Element contextElement) throws XPathException {
+
+ String slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL10_PREFIX, XMLNamespaceConstants.SL10_NS_URI);
+ if (slPrefix == null)
+ slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL11_PREFIX, XMLNamespaceConstants.SL11_NS_URI);
+
+ if (slPrefix == null)
+ slPrefix = checkSLnsDeclaration(contextElement, XMLNamespaceConstants.SL12_PREFIX, XMLNamespaceConstants.SL12_NS_URI);
+
+ return slPrefix;
+
+ }
+
+ /**
+ * Checks if the context element has an attribute <code>xmlns:slPrefix</code> and
+ * if the prefix of that attribute corresponds with a valid SecurityLayer namespace.
+ *
+ * @param contextElement The element to be checked.
+ * @param slPrefix The prefix which should be checked. Must be a valid SecurityLayer
+ * namespace prefix.
+ * @param slNameSpace The SecurityLayer namespace that corresponds to the specified prefix.
+ *
+ * @return The valid SecurityLayer prefix or <code>null</code> if this prefix is
+ * not used.
+ * @throws XPathException
+ */
+ private static String checkSLnsDeclaration(Element contextElement, String slPrefix, String slNameSpace)
+ throws XPathException
+ {
+ String nsAtt = "xmlns:" + slPrefix;
+ String nameSpace = contextElement.getAttribute(nsAtt);
+ if (nameSpace == "") {
+ return null;
+
+ } else {
+ // check if namespace is correct
+ if (nameSpace.equals(slNameSpace))
+ return slPrefix;
+ else
+ throw new XPathException("Unknown Namespace declaration");
+
+ }
+ }
+
+}