com.connexta.arbitro.ctx.xacml3.XACML3EvaluationCtx.java Source code

Java tutorial

Introduction

Here is the source code for com.connexta.arbitro.ctx.xacml3.XACML3EvaluationCtx.java

Source

/*
*  Copyright (c) WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
*  WSO2 Inc. licenses this file to you under the Apache License,
*  Version 2.0 (the "License"); you may not use this file except
*  in compliance with the License.
*  You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package com.connexta.arbitro.ctx.xacml3;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.NamespaceContext;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.connexta.arbitro.PolicyReference;
import com.connexta.arbitro.XACMLConstants;
import com.connexta.arbitro.attr.StringAttribute;
import com.connexta.arbitro.ctx.AbstractRequestCtx;
import com.connexta.arbitro.finder.ResourceFinderResult;
import com.connexta.arbitro.xacml3.Attributes;
import com.connexta.arbitro.xacml3.AttributesReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.connexta.arbitro.Balana;
import com.connexta.arbitro.DOMHelper;
import com.connexta.arbitro.DefaultNamespaceContext;
import com.connexta.arbitro.PDPConfig;
import com.connexta.arbitro.attr.AttributeValue;
import com.connexta.arbitro.attr.BagAttribute;
import com.connexta.arbitro.attr.xacml3.XPathAttribute;
import com.connexta.arbitro.cond.EvaluationResult;
import com.connexta.arbitro.ctx.Attribute;
import com.connexta.arbitro.ctx.BasicEvaluationCtx;
import com.connexta.arbitro.ctx.EvaluationCtx;
import com.connexta.arbitro.ctx.Status;
import com.connexta.arbitro.xacml3.MultiRequests;
import com.connexta.arbitro.xacml3.MultipleCtxResult;
import com.connexta.arbitro.xacml3.RequestReference;

/**
 * This is implementation of XACML3 evaluation context
 *
 */
public class XACML3EvaluationCtx extends BasicEvaluationCtx {

    /**
     * Attributes set of the request
     */
    private Set<Attributes> attributesSet;

    /**
     * multiple content selectors.
     */
    private Set<Attributes> multipleContentSelectors;

    /**
     * whether multiple attributes are present or not
     */
    private boolean multipleAttributes;

    /**
     * Set of policy references
     */
    private Set<PolicyReference> policyReferences;

    /**
     * attributes categorized as Map
     *
     * Category  --> Attributes Set
     */
    private Map<String, List<Attributes>> mapAttributes;

    /**
     * XACML3 request
     */
    private RequestCtx requestCtx;

    /**
     * XACML3 request scope. used with multiple resource profile
     */
    private Attribute resourceScopeAttribute;

    /**
     * XACML3 request scope. used with hierarchical resource
     */
    private int resourceScope;

    /**
     * XACML 3 request resource id.  used with hierarchical resource
     */
    private Attribute resourceId;

    /**
     * logger
     */
    private static Log logger = LogFactory.getLog(XACML3EvaluationCtx.class);

    /**
     * Creates a new <code>XACML3EvaluationCtx</code>
     *
     * @param requestCtx  XACML3  RequestCtx
     * @param pdpConfig PDP configurations
     */
    public XACML3EvaluationCtx(RequestCtx requestCtx, PDPConfig pdpConfig) {

        // initialize the cached date/time values so it's clear we haven't
        // retrieved them yet
        currentDate = null;
        currentTime = null;
        currentDateTime = null;

        mapAttributes = new HashMap<String, List<Attributes>>();

        attributesSet = requestCtx.getAttributesSet();
        this.pdpConfig = pdpConfig;
        this.requestCtx = requestCtx;

        setupAttributes(attributesSet, mapAttributes);
    }

    public EvaluationResult getAttribute(URI type, URI id, String issuer, URI category) {

        List<AttributeValue> attributeValues = new ArrayList<AttributeValue>();
        List<Attributes> attributesSet = mapAttributes.get(category.toString());
        if (attributesSet != null && attributesSet.size() > 0) {
            Set<Attribute> attributeSet = attributesSet.get(0).getAttributes();
            for (Attribute attribute : attributeSet) {
                if (attribute.getId().toString().equals(id.toString())
                        && attribute.getType().toString().equals(type.toString())
                        && (issuer == null || issuer.equals(attribute.getIssuer()))
                        && attribute.getValue() != null) {
                    List<AttributeValue> attributeValueList = attribute.getValues();
                    for (AttributeValue attributeVal : attributeValueList) {
                        attributeValues.add(attributeVal);
                    }
                }
            }

            if (attributeValues.size() < 1) {
                return callHelper(type, id, issuer, category);
            }
        }
        // if we got here, then we found at least one useful AttributeValue
        return new EvaluationResult(new BagAttribute(type, attributeValues));
    }

    public EvaluationResult getAttribute(String path, URI type, URI category, URI contextSelector,
            String xpathVersion) {

        if (pdpConfig.getAttributeFinder() == null) {

            logger.warn("Context tried to invoke AttributeFinder but was " + "not configured with one");
            return new EvaluationResult(BagAttribute.createEmptyBag(type));
        }

        List<Attributes> attributesSet = null;

        if (category != null) {
            attributesSet = mapAttributes.get(category.toString());
        }

        if (attributesSet != null && attributesSet.size() > 0) {
            Attributes attributes = attributesSet.get(0);
            Object content = attributes.getContent();
            if (content instanceof Node) {
                Node root = (Node) content;
                if (contextSelector != null && contextSelector.toString().trim().length() > 0) {
                    for (Attribute attribute : attributes.getAttributes()) {
                        if (attribute.getId().equals(contextSelector)) {
                            List<AttributeValue> values = attribute.getValues();
                            for (AttributeValue value : values) {
                                if (value instanceof XPathAttribute) {
                                    XPathAttribute xPathAttribute = (XPathAttribute) value;
                                    if (xPathAttribute.getXPathCategory().equals(category.toString())) {
                                        return pdpConfig.getAttributeFinder().findAttribute(path,
                                                xPathAttribute.getValue(), type, root, this, xpathVersion);
                                    }
                                }
                            }
                        }
                    }
                } else {
                    return pdpConfig.getAttributeFinder().findAttribute(path, null, type, root, this, xpathVersion);
                }
            }
        }

        return new EvaluationResult(BagAttribute.createEmptyBag(type));
    }

    public int getXacmlVersion() {
        return requestCtx.getXacmlVersion();
    }

    /**
     * Generic routine for resource, attribute and environment attributes to build the lookup map
     * for each. The Form is a Map that is indexed by the String form of the category ids, and that
     * contains Sets at each entry with all attributes that have that id
     *
     * @param attributeSet  The attributes used to build a lookup map for attributes
     * @param mapAttributes The map which will have the attributes put into it
     *
     */
    private void setupAttributes(Set<Attributes> attributeSet, Map<String, List<Attributes>> mapAttributes) {
        for (Attributes attributes : attributeSet) {
            String category = attributes.getCategory().toString();
            for (Attribute attribute : attributes.getAttributes()) {
                if (XACMLConstants.RESOURCE_CATEGORY.equals(category)) {
                    if (XACMLConstants.RESOURCE_SCOPE_2_0.equals(attribute.getId().toString())) {
                        resourceScopeAttribute = attribute;
                        AttributeValue value = attribute.getValue();
                        if (value instanceof StringAttribute) {
                            String scope = ((StringAttribute) value).getValue();
                            if (scope.equals("Children")) {
                                resourceScope = XACMLConstants.SCOPE_CHILDREN;
                            } else if (scope.equals("Descendants")) {
                                resourceScope = XACMLConstants.SCOPE_DESCENDANTS;
                            }
                        } else {
                            logger.error("scope attribute must be a string"); //TODO
                            //throw new ParsingException("scope attribute must be a string");
                        }
                    }

                    if (XACMLConstants.RESOURCE_ID.equals(attribute.getId().toString())) {
                        if (resourceId == null) { //TODO  when there are more than one resource ids??
                            resourceId = attribute;
                        }
                    }
                }

                if (attribute.getId().toString().equals(XACMLConstants.MULTIPLE_CONTENT_SELECTOR)) {
                    if (multipleContentSelectors == null) {
                        multipleContentSelectors = new HashSet<Attributes>();
                    }
                    multipleContentSelectors.add(attributes);
                }
            }

            if (mapAttributes.containsKey(category)) {
                List<Attributes> set = mapAttributes.get(category);
                set.add(attributes);
                multipleAttributes = true;
            } else {
                List<Attributes> set = new ArrayList<Attributes>();
                set.add(attributes);
                mapAttributes.put(category, set);
            }
        }
    }

    public MultipleCtxResult getMultipleEvaluationCtx() {

        Set<EvaluationCtx> evaluationCtxSet = new HashSet<EvaluationCtx>();
        MultiRequests multiRequests = requestCtx.getMultiRequests();

        // 1st check whether there is a multi request attribute
        if (multiRequests != null) {

            MultipleCtxResult result = processMultiRequestElement(this);
            if (result.isIndeterminate()) {
                return result;
            } else {
                evaluationCtxSet.addAll(result.getEvaluationCtxSet());
            }
        }

        // 2nd check repeated values for category attribute
        if (evaluationCtxSet.size() > 0) {
            Set<EvaluationCtx> newSet = new HashSet<EvaluationCtx>(evaluationCtxSet);
            for (EvaluationCtx evaluationCtx : newSet) {
                if (((XACML3EvaluationCtx) evaluationCtx).isMultipleAttributes()) {
                    evaluationCtxSet.remove(evaluationCtx);
                    MultipleCtxResult result = processMultipleAttributes((XACML3EvaluationCtx) evaluationCtx);
                    if (result.isIndeterminate()) {
                        return result;
                    } else {
                        evaluationCtxSet.addAll(result.getEvaluationCtxSet());
                    }
                }
            }
        } else {
            if (multipleAttributes) {
                MultipleCtxResult result = processMultipleAttributes(this);
                if (result.isIndeterminate()) {
                    return result;
                } else {
                    evaluationCtxSet.addAll(result.getEvaluationCtxSet());
                }
            }
        }

        // 3rd check for both scope and multiple-content-selector attributes. Spec does not mention
        // which one to pick when both are present, there for high priority has given to scope
        // attribute
        if (evaluationCtxSet.size() > 0) {
            Set<EvaluationCtx> newSet = new HashSet<EvaluationCtx>(evaluationCtxSet);
            for (EvaluationCtx evaluationCtx : newSet) {
                if (((XACML3EvaluationCtx) evaluationCtx).getResourceScope() != XACMLConstants.SCOPE_IMMEDIATE) {
                    evaluationCtxSet.remove(evaluationCtx);
                    MultipleCtxResult result = processHierarchicalAttributes((XACML3EvaluationCtx) evaluationCtx);
                    if (result.isIndeterminate()) {
                        return result;
                    } else {
                        evaluationCtxSet.addAll(result.getEvaluationCtxSet());
                    }
                } else if (((XACML3EvaluationCtx) evaluationCtx).getMultipleContentSelectors() != null) {
                    MultipleCtxResult result = processMultipleContentSelectors((XACML3EvaluationCtx) evaluationCtx);
                    if (result.isIndeterminate()) {
                        return result;
                    } else {
                        evaluationCtxSet.addAll(result.getEvaluationCtxSet());
                    }
                }
            }
        } else {
            if (resourceScope != XACMLConstants.SCOPE_IMMEDIATE) {
                MultipleCtxResult result = processHierarchicalAttributes(this);
                if (result.isIndeterminate()) {
                    return result;
                } else {
                    evaluationCtxSet.addAll(result.getEvaluationCtxSet());
                }
            } else if (multipleContentSelectors != null) {
                MultipleCtxResult result = processMultipleContentSelectors(this);
                if (result.isIndeterminate()) {
                    return result;
                } else {
                    evaluationCtxSet.addAll(result.getEvaluationCtxSet());
                }
            }
        }

        if (evaluationCtxSet.size() > 0) {
            return new MultipleCtxResult(evaluationCtxSet);
        } else {
            evaluationCtxSet.add(this);
            return new MultipleCtxResult(evaluationCtxSet);
        }
    }

    /**
     * Process multi request element
     * 
     * @param evaluationCtx <code>XACML3EvaluationCtx</code>
     * @return <code>MultipleCtxResult</code>
     */
    private MultipleCtxResult processMultiRequestElement(XACML3EvaluationCtx evaluationCtx) {

        Set<EvaluationCtx> children = new HashSet<EvaluationCtx>();
        MultiRequests multiRequests = requestCtx.getMultiRequests();

        if (multiRequests == null) {
            return new MultipleCtxResult(children);
        }

        Set<RequestReference> requestReferences = multiRequests.getRequestReferences();
        for (RequestReference reference : requestReferences) {
            Set<AttributesReference> attributesReferences = reference.getReferences();
            if (attributesReferences != null && attributesReferences.size() > 0) {
                Set<Attributes> attributes = new HashSet<Attributes>();
                for (AttributesReference attributesReference : attributesReferences) {
                    String referenceId = attributesReference.getId();
                    if (referenceId != null) {
                        Attributes newAttributes = null;
                        for (Attributes attribute : evaluationCtx.getAttributesSet()) {
                            // check equal with reference id
                            if (attribute.getId() != null && attribute.getId().equals(referenceId)) {
                                newAttributes = attribute;
                            }
                        }
                        if (newAttributes != null) {
                            attributes.add(newAttributes);
                        } else {
                            // This must be only for one result. But here it is used to create error for
                            List<String> code = new ArrayList<String>();
                            code.add(Status.STATUS_SYNTAX_ERROR);
                            return new MultipleCtxResult(new Status(code, "Invalid reference to attributes"));
                        }
                    }
                }
                RequestCtx ctx = new RequestCtx(attributes, null);
                children.add(new XACML3EvaluationCtx(ctx, pdpConfig));
            }
        }

        return new MultipleCtxResult(children);
    }

    /**
     * Process multiple attributes with same category
     * 
     * @param evaluationCtx <code>XACML3EvaluationCtx</code>
     * @return <code>MultipleCtxResult</code>
     */
    private MultipleCtxResult processMultipleAttributes(XACML3EvaluationCtx evaluationCtx) {

        Set<EvaluationCtx> children = new HashSet<EvaluationCtx>();

        Map<String, List<Attributes>> mapAttributes = evaluationCtx.getMapAttributes();

        Set<Set<Attributes>> tempRequestAttributes = new HashSet<Set<Attributes>>(
                Arrays.asList(evaluationCtx.getAttributesSet()));

        for (Map.Entry<String, List<Attributes>> mapAttributesEntry : mapAttributes.entrySet()) {
            if (mapAttributesEntry.getValue().size() > 1) {
                Set<Set<Attributes>> temp = new HashSet<Set<Attributes>>();
                for (Attributes attributesElement : mapAttributesEntry.getValue()) {
                    for (Set<Attributes> tempRequestAttribute : tempRequestAttributes) {
                        Set<Attributes> newSet = new HashSet<Attributes>(tempRequestAttribute);
                        newSet.removeAll(mapAttributesEntry.getValue());
                        newSet.add(attributesElement);
                        temp.add(newSet);
                    }
                }
                tempRequestAttributes = temp;
            }
        }

        for (Set<Attributes> ctx : tempRequestAttributes) {
            RequestCtx requestCtx = new RequestCtx(ctx, null);
            children.add(new XACML3EvaluationCtx(requestCtx, pdpConfig));
        }

        return new MultipleCtxResult(children);
    }

    /**
     *
     * @param evaluationCtx
     * @return
     */
    private MultipleCtxResult processHierarchicalAttributes(XACML3EvaluationCtx evaluationCtx) {

        ResourceFinderResult resourceResult = null;
        Set<EvaluationCtx> children = new HashSet<EvaluationCtx>();

        Attribute resourceId = evaluationCtx.getResourceId();
        if (resourceId != null) {

            if (evaluationCtx.getResourceScope() == XACMLConstants.SCOPE_CHILDREN) {
                resourceResult = pdpConfig.getResourceFinder().findChildResources(resourceId.getValue(),
                        evaluationCtx);
            } else if (evaluationCtx.getResourceScope() == XACMLConstants.SCOPE_DESCENDANTS) {
                resourceResult = pdpConfig.getResourceFinder().findDescendantResources(resourceId.getValue(),
                        evaluationCtx);
            } else {
                logger.error("Unknown scope type: ");
                //TODO
            }
        } else {
            logger.error("ResourceId Attribute is NULL: ");
            // TODO
        }

        if (resourceResult == null || resourceResult.isEmpty()) {
            logger.error("Resource Finder result is NULL: ");
            // TODO
        } else {
            for (AttributeValue resource : resourceResult.getResources()) {
                Set<Attributes> newSet = new HashSet<Attributes>(evaluationCtx.getAttributesSet());
                Attributes resourceAttributes = null;
                for (Attributes attributes : newSet) {
                    if (XACMLConstants.RESOURCE_CATEGORY.equals(attributes.getCategory().toString())) {
                        Set<Attribute> attributeSet = new HashSet<Attribute>(attributes.getAttributes());
                        attributeSet.remove(resourceScopeAttribute);
                        attributeSet.remove(resourceId);
                        try {
                            Attribute attribute = new Attribute(new URI(XACMLConstants.RESOURCE_ID),
                                    resourceId.getIssuer(), null, resource, resourceId.isIncludeInResult(),
                                    XACMLConstants.XACML_VERSION_3_0);
                            attributeSet.add(attribute);
                            Attributes newAttributes = new Attributes(new URI(XACMLConstants.RESOURCE_CATEGORY),
                                    (Node) attributes.getContent(), attributeSet, attributes.getId());
                            newSet.add(newAttributes);
                            resourceAttributes = attributes;
                        } catch (URISyntaxException e) {
                            //ignore
                        }
                        break;
                    }
                }
                if (resourceAttributes != null) {
                    newSet.remove(resourceAttributes);
                    children.add(new XACML3EvaluationCtx(new RequestCtx(newSet, null), pdpConfig));
                }
            }
        }

        return new MultipleCtxResult(children);

    }

    /**
     *
     * @param evaluationCtx
     * @return
     */
    private MultipleCtxResult processMultipleContentSelectors(XACML3EvaluationCtx evaluationCtx) {

        Set<EvaluationCtx> children = new HashSet<EvaluationCtx>();
        Set<Attributes> newAttributesSet = new HashSet<Attributes>();

        for (Attributes attributes : evaluationCtx.getMultipleContentSelectors()) {
            Set<Attribute> newAttributes = null;
            Attribute oldAttribute = null;
            Object content = attributes.getContent();
            if (content != null && content instanceof Node) {
                Node root = (Node) content;
                for (Attribute attribute : attributes.getAttributes()) {
                    oldAttribute = attribute;
                    if (attribute.getId().toString().equals(XACMLConstants.MULTIPLE_CONTENT_SELECTOR)) {
                        List<AttributeValue> values = attribute.getValues();
                        for (AttributeValue value : values) {
                            if (value instanceof XPathAttribute) {
                                XPathAttribute xPathAttribute = (XPathAttribute) value;
                                if (xPathAttribute.getXPathCategory().equals(attributes.getCategory().toString())) {
                                    Set<String> xPaths = getChildXPaths(root, xPathAttribute.getValue());
                                    for (String xPath : xPaths) {
                                        try {
                                            AttributeValue newValue = Balana.getInstance().getAttributeFactory()
                                                    .createValue(value.getType(), xPath,
                                                            new String[] { xPathAttribute.getXPathCategory() });
                                            Attribute newAttribute = new Attribute(
                                                    new URI(XACMLConstants.CONTENT_SELECTOR), attribute.getIssuer(),
                                                    attribute.getIssueInstant(), newValue,
                                                    attribute.isIncludeInResult(),
                                                    XACMLConstants.XACML_VERSION_3_0);
                                            if (newAttributes == null) {
                                                newAttributes = new HashSet<Attribute>();
                                            }
                                            newAttributes.add(newAttribute);
                                        } catch (Exception e) {
                                            e.printStackTrace(); // TODO
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if (newAttributes != null) {
                    attributes.getAttributes().remove(oldAttribute);
                    for (Attribute attribute : newAttributes) {
                        Set<Attribute> set = new HashSet<Attribute>(attributes.getAttributes());
                        set.add(attribute);
                        Attributes attr = new Attributes(attributes.getCategory(), attributes.getContent(), set,
                                attributes.getId());
                        newAttributesSet.add(attr);
                    }
                    evaluationCtx.getAttributesSet().remove(attributes);
                }
            }
        }

        for (Attributes attributes : newAttributesSet) {
            Set<Attributes> set = new HashSet<Attributes>(evaluationCtx.getAttributesSet());
            set.add(attributes);
            RequestCtx requestCtx = new RequestCtx(set, null);
            children.add(new XACML3EvaluationCtx(requestCtx, pdpConfig));
        }

        return new MultipleCtxResult(children);

    }

    /**
     * Changes the value of the resource-id attribute in this context. This is useful when you have
     * multiple resources (ie, a scope other than IMMEDIATE), and you need to keep changing only the
     * resource-id to evaluate the different effective requests.
     * 
     * @param resourceId  resourceId the new resource-id value
     * @param attributesSet a <code>Set</code> of <code>Attributes</code>
     */
    public void setResourceId(AttributeValue resourceId, Set<Attributes> attributesSet) {

        for (Attributes attributes : attributesSet) {
            if (XACMLConstants.RESOURCE_CATEGORY.equals(attributes.getCategory().toString())) {
                Set<Attribute> attributeSet = attributes.getAttributes();
                Set<Attribute> newSet = new HashSet<Attribute>(attributeSet);
                Attribute resourceIdAttribute = null;

                for (Attribute attribute : newSet) {
                    if (XACMLConstants.RESOURCE_ID.equals(attribute.getId().toString())) {
                        resourceIdAttribute = attribute;
                        attributeSet.remove(attribute);
                    } else if (XACMLConstants.RESOURCE_SCOPE_2_0.equals(attribute.getId().toString())) {
                        attributeSet.remove(attribute);
                    }
                }

                if (resourceIdAttribute != null) {
                    attributeSet.add(new Attribute(resourceIdAttribute.getId(), resourceIdAttribute.getIssuer(),
                            resourceIdAttribute.getIssueInstant(), resourceId,
                            resourceIdAttribute.isIncludeInResult(), XACMLConstants.XACML_VERSION_3_0));
                }
                break;
            }

        }
    }

    private Set<String> getChildXPaths(Node root, String xPath) {

        Set<String> xPaths = new HashSet<String>();
        NamespaceContext namespaceContext = null;

        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();

        if (namespaceContext == null) {

            //see if the request root is in a namespace
            String namespace = null;
            if (root != null) {
                namespace = root.getNamespaceURI();
            }
            // name spaces are used, so we need to lookup the correct
            // prefix to use in the search string
            NamedNodeMap namedNodeMap = root.getAttributes();

            Map<String, String> nsMap = new HashMap<String, String>();
            if (namedNodeMap != null) {
                for (int i = 0; i < namedNodeMap.getLength(); i++) {
                    Node n = namedNodeMap.item(i);
                    // we found the matching namespace, so get the prefix
                    // and then break out
                    String prefix = DOMHelper.getLocalName(n);
                    String nodeValue = n.getNodeValue();
                    nsMap.put(prefix, nodeValue);
                }
            }

            // if there is not any namespace is defined for content element, default XACML request
            //  name space would be there.
            if (XACMLConstants.REQUEST_CONTEXT_3_0_IDENTIFIER.equals(namespace)
                    || XACMLConstants.REQUEST_CONTEXT_2_0_IDENTIFIER.equals(namespace)
                    || XACMLConstants.REQUEST_CONTEXT_1_0_IDENTIFIER.equals(namespace)) {
                nsMap.put("xacml", namespace);
            }

            namespaceContext = new DefaultNamespaceContext(nsMap);
        }

        xpath.setNamespaceContext(namespaceContext);

        try {
            XPathExpression expression = xpath.compile(xPath);
            NodeList matches = (NodeList) expression.evaluate(root, XPathConstants.NODESET);
            if (matches != null && matches.getLength() > 0) {

                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 = "/" + DOMHelper.getLocalName(node);
                    }
                    String newXPath = '(' + xPath + ")[" + (i + 1) + ']';
                    xPaths.add(newXPath);
                }
            }
        } catch (Exception e) {
            // TODO
        }

        return xPaths;
    }

    public boolean isMultipleAttributes() {
        return multipleAttributes;
    }

    public AbstractRequestCtx getRequestCtx() {
        return requestCtx;
    }

    /**
     *
     * @return returns a Set of <code>PolicyReference</code>s
     */
    public Set<PolicyReference> getPolicyReferences() {
        return policyReferences;
    }

    /**
     *
     * @param policyReferences The Set of PolicyRefences to be used for the setter method
     */
    public void setPolicyReferences(Set<PolicyReference> policyReferences) {
        this.policyReferences = policyReferences;
    }

    /**
     *
     * @param category The category of attributes to retrieve
     * @return A List of attributes for the provided category
     */
    public List<Attributes> getAttributes(String category) {
        return mapAttributes.get(category);
    }

    public Set<Attributes> getMultipleContentSelectors() {
        return multipleContentSelectors;
    }

    public Map<String, List<Attributes>> getMapAttributes() {
        return mapAttributes;
    }

    public Set<Attributes> getAttributesSet() {
        return attributesSet;
    }

    public Attribute getResourceId() {
        return resourceId;
    }

    public int getResourceScope() {
        return resourceScope;
    }

    public Attribute getResourceScopeAttribute() {
        return resourceScopeAttribute;
    }
}