public EvaluationResult findAttribute(String path, Node namespaceNode,
URI type, EvaluationCtx context,
String xpathVersion) {
// we only support 1.0
if (! xpathVersion.equals(PolicyMetaData.XPATH_1_0_IDENTIFIER))
return new EvaluationResult(BagAttribute.createEmptyBag(type));
// get the DOM root of the request document
Node root = context.getRequestRoot();
// if we were provided with a non-null namespace node, then use it
// to resolve namespaces, otherwise use the context root node
Node nsNode = (namespaceNode != null) ? namespaceNode : root;
// setup the root path (pre-pended to the context path), which...
String rootPath = "";
// ...only has content if the context path is relative
if (path.charAt(0) != '/') {
String rootName = root.getLocalName();
// see if the request root is in a namespace
String namespace = root.getNamespaceURI();
if (namespace == null) {
// no namespacing, so we're done
rootPath = "/" + rootName + "/";
} else {
// namespaces are used, so we need to lookup the correct
// prefix to use in the search string
NamedNodeMap nmap = namespaceNode.getAttributes();
rootPath = null;
for (int i = 0; i < nmap.getLength(); i++) {
Node n = nmap.item(i);
if (n.getNodeValue().equals(namespace)) {
// we found the matching namespace, so get the prefix
// and then break out
String name = SunxacmlUtil.getNodeName(n);
int pos = name.indexOf(':');
if (pos == -1) {
// the namespace was the default namespace
rootPath = "/";
} else {
// we found a prefixed namespace
rootPath = "/" + name.substring(pos + 1);
}
// finish off the string
rootPath += ":" + rootName + "/";
break;
}
}
// if the rootPath is still null, then we don't have any
// definitions for the namespace
if (rootPath == null)
return createProcessingError("Failed to map a namespace" +
" in an XPath expression");
}
}
// now do the query, pre-pending the root path to the context path
NodeList matches = null;
try {
// NOTE: see comments in XALAN docs about why this is slow
matches = XPathAPI.selectNodeList(root, rootPath + path, nsNode);
} catch (Exception e) {
// in the case of any exception, we need to return an error
return createProcessingError("error in XPath: " + e.getMessage());
}
if (matches.getLength() == 0) {
// we didn't find anything, so we return an empty bag
return new EvaluationResult(BagAttribute.createEmptyBag(type));
}
// there was at least one match, so try to generate the values
try {
ArrayList list = new ArrayList();
AttributeFactory attrFactory = AttributeFactory.getInstance();
for (int i = 0; i < matches.getLength(); i++) {
String text = null;
Node node = matches.item(i);
short nodeType = node.getNodeType();
// see if this is straight text, or a node with data under
// it and then get the values accordingly
if ((nodeType == Node.CDATA_SECTION_NODE) ||
(nodeType == Node.COMMENT_NODE) ||
(nodeType == Node.TEXT_NODE) ||
(nodeType == Node.ATTRIBUTE_NODE)) {
// there is no child to this node
text = node.getNodeValue();
} else {
// the data is in a child node
text = node.getFirstChild().getNodeValue();
}
list.add(attrFactory.createValue(type, text));
}
return new EvaluationResult(new BagAttribute(type, list));
} catch (ParsingException pe) {
return createProcessingError(pe.getMessage());
} catch (UnknownIdentifierException uie) {
return createProcessingError("unknown attribute type: " + type);
}