Search in sources :

Example 1 with VariableReference

use of org.ow2.authzforce.core.pdp.api.expression.VariableReference in project core by authzforce.

the class PolicyEvaluators method getInstanceGeneric.

/**
 * Generic creation of PolicySet evaluator
 *
 * @param policySetRefChainWithArgIffRefTarget null/empty if {@code policyElement} is the root policySet; else it is the chain of top-level (as opposed to nested inline) PolicySets linked by PolicySetIdReferences from the root
 *                                             PolicySet up to (and including) the top-level (PolicySetIdReference-targeted) PolicySet that encloses or is {@code policyElement}
 */
private static <TLPEE extends TopLevelPolicyElementEvaluator, COMBINED_EVALUATOR extends PolicyEvaluator> TLPEE getInstanceGeneric(final PolicySetElementEvaluatorFactory<TLPEE, COMBINED_EVALUATOR> policyEvaluatorFactory, final PolicySet policyElement, final Deque<String> policySetRefChainWithArgIffRefTarget) throws IllegalArgumentException {
    assert policyEvaluatorFactory != null && policyElement != null;
    // final Set<PrimaryPolicyMetadata> enclosedPolicies = HashCollections.newUpdatableSet();
    final String policyId = policyElement.getPolicySetId();
    final BooleanEvaluator targetEvaluator = TargetEvaluators.getInstance(policyElement.getTarget(), policyEvaluatorFactory.expressionFactory, policyEvaluatorFactory.defaultXPathCompiler);
    /*
         * Elements defined in xs:choice of PolicySetType in XACML schema (Policy(Set)/Policy(Set)IdReference/CombinerParameters/Policy(Set)CombinerParameters
         */
    final List<Serializable> jaxbPolicySetChoiceElements = policyElement.getPolicySetsAndPoliciesAndPolicySetIdReferences();
    /*
         * Prepare the list of evaluators combined by the combining algorithm in this PolicySet, i.e. Policy(Set)/Policy(Set)IdReference evaluators. combinedEvaluators.size() <=
         * jaxbPolicySetChoiceElements.size() since combinedEvaluators does not include *CombinerParameter evaluators
         */
    final List<COMBINED_EVALUATOR> combinedEvaluators = new ArrayList<>(jaxbPolicySetChoiceElements.size());
    /*
         * Why isn't there any VariableDefinition in XACML PolicySet like in Policy? If there were, we would keep a copy of variable IDs defined in this policy, to remove them from the global manager
         * at the end of parsing this PolicySet. They should not be visible outside the scope of this.
         * <p>
         * final Set<String> variableIds = HashCollections.newUpdatableSet(jaxbPolicySetChoiceElements.size());
         */
    /*
         * Map to get child Policies by their ID so that we can resolve Policies associated with PolicyCombinerParameters Size cannot get bigger than jaxbPolicySetChoiceElements.size()
         */
    final Map<String, COMBINED_EVALUATOR> childPolicyEvaluatorsByPolicyId = HashCollections.newUpdatableMap(jaxbPolicySetChoiceElements.size());
    /*
         * Map to get child PolicySets by their ID so that we can resolve PolicySets associated with PolicySetCombinerParameters Size cannot get bigger than jaxbPolicySetChoiceElements.size()
         */
    final Map<String, COMBINED_EVALUATOR> childPolicySetEvaluatorsByPolicySetId = HashCollections.newUpdatableMap(jaxbPolicySetChoiceElements.size());
    /*
         * *CombinerParameters (combining algorithm parameters), size <= jaxbPolicySetChoiceElements.size()
         */
    final List<CombiningAlgParameter<? extends COMBINED_EVALUATOR>> combiningAlgParameters = new ArrayList<>(jaxbPolicySetChoiceElements.size());
    int childIndex = 0;
    for (final Serializable policyChildElt : jaxbPolicySetChoiceElements) {
        if (policyChildElt instanceof PolicyCombinerParameters) {
            final String combinedPolicyId = ((PolicyCombinerParameters) policyChildElt).getPolicyIdRef();
            final COMBINED_EVALUATOR childPolicyEvaluator = childPolicyEvaluatorsByPolicyId.get(combinedPolicyId);
            if (childPolicyEvaluator == null) {
                throw new IllegalArgumentException(policyEvaluatorFactory.policyMetadata + ":  invalid PolicyCombinerParameters: referencing undefined child Policy #" + combinedPolicyId + " (no such policy defined before this element)");
            }
            final BaseCombiningAlgParameter<COMBINED_EVALUATOR> combiningAlgParameter;
            try {
                combiningAlgParameter = new BaseCombiningAlgParameter<>(childPolicyEvaluator, ((CombinerParametersType) policyChildElt).getCombinerParameters(), policyEvaluatorFactory.expressionFactory, policyEvaluatorFactory.defaultXPathCompiler);
            } catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException(policyEvaluatorFactory.policyMetadata + ": invalid child #" + childIndex + " (PolicyCombinerParameters)", e);
            }
            combiningAlgParameters.add(combiningAlgParameter);
        } else if (policyChildElt instanceof PolicySetCombinerParameters) {
            final String combinedPolicySetId = ((PolicySetCombinerParameters) policyChildElt).getPolicySetIdRef();
            final COMBINED_EVALUATOR combinedPolicySetEvaluator = childPolicySetEvaluatorsByPolicySetId.get(combinedPolicySetId);
            if (combinedPolicySetEvaluator == null) {
                throw new IllegalArgumentException(policyEvaluatorFactory.policyMetadata + ":  invalid PolicySetCombinerParameters: referencing undefined child PolicySet #" + combinedPolicySetId + " (no such policySet defined before this element)");
            }
            final BaseCombiningAlgParameter<COMBINED_EVALUATOR> combiningAlgParameter;
            try {
                combiningAlgParameter = new BaseCombiningAlgParameter<>(combinedPolicySetEvaluator, ((CombinerParametersType) policyChildElt).getCombinerParameters(), policyEvaluatorFactory.expressionFactory, policyEvaluatorFactory.defaultXPathCompiler);
            } catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException(policyEvaluatorFactory.policyMetadata + ": invalid child #" + childIndex + " (PolicySetCombinerParameters)", e);
            }
            combiningAlgParameters.add(combiningAlgParameter);
        } else if (policyChildElt instanceof JAXBElement) {
            final JAXBElement<?> jaxbPolicyChildElt = (JAXBElement<?>) policyChildElt;
            final String eltNameLocalPart = jaxbPolicyChildElt.getName().getLocalPart();
            if (eltNameLocalPart.equals(XacmlNodeName.POLICY_ID_REFERENCE.value())) {
                final IdReferenceType policyChildIdRef = (IdReferenceType) jaxbPolicyChildElt.getValue();
                final COMBINED_EVALUATOR childEvaluator = policyEvaluatorFactory.getChildPolicyRefEvaluator(childIndex, TopLevelPolicyElementType.POLICY, policyChildIdRef, null);
                combinedEvaluators.add(childEvaluator);
                final COMBINED_EVALUATOR duplicate = childPolicySetEvaluatorsByPolicySetId.putIfAbsent(childEvaluator.getPolicyId(), childEvaluator);
                if (duplicate != null) {
                    throw new IllegalArgumentException("Duplicate PolicyIdReference's id = " + childEvaluator.getPolicyId());
                }
            } else if (eltNameLocalPart.equals(XacmlNodeName.POLICYSET_ID_REFERENCE.value())) {
                final IdReferenceType policyChildIdRef = (IdReferenceType) jaxbPolicyChildElt.getValue();
                final String policyChildId = policyChildIdRef.getValue();
                /*
                     * Add this new reference to policyChildIdRef to the policyRef chain arg of getChildPolicyRefEvaluator(...). If policySetRefChainWithArgIffRefTarget is null/empty, policyElement is
                     * the root policy (no ancestor in the chain), therefore it should be added before policyChildIdRef, as the antecedent; Else non-empty policySetRefChainWithArgIffRefTarget's last
                     * item is either policyElement (iff it is a policy ref's target) or the top-level (as opposed to nested inline) PolicySet that encloses policyElement, in which either case we just
                     * add policyChildIdRef to the chain.
                     */
                final Deque<String> newPolicySetRefChainWithArgIffRefTarget = policySetRefChainWithArgIffRefTarget == null || policySetRefChainWithArgIffRefTarget.isEmpty() ? new ArrayDeque<>(Arrays.asList(policyId, policyChildId)) : policyEvaluatorFactory.joinPolicySetRefChains(policySetRefChainWithArgIffRefTarget, Collections.singletonList(policyChildId));
                final COMBINED_EVALUATOR childEvaluator = policyEvaluatorFactory.getChildPolicyRefEvaluator(childIndex, TopLevelPolicyElementType.POLICY_SET, policyChildIdRef, newPolicySetRefChainWithArgIffRefTarget);
                combinedEvaluators.add(childEvaluator);
                final COMBINED_EVALUATOR duplicate = childPolicySetEvaluatorsByPolicySetId.put(policyChildId, childEvaluator);
                if (duplicate != null) {
                    throw new IllegalArgumentException("Duplicate PolicySetIdReference's id = " + policyChildId);
                }
            } else if (eltNameLocalPart.equals(XacmlNodeName.COMBINER_PARAMETERS.value())) {
                /*
                     * CombinerParameters that is not Policy(Set)CombinerParameters already tested before
                     */
                final BaseCombiningAlgParameter<COMBINED_EVALUATOR> combiningAlgParameter;
                try {
                    combiningAlgParameter = new BaseCombiningAlgParameter<>(null, ((CombinerParametersType) jaxbPolicyChildElt.getValue()).getCombinerParameters(), policyEvaluatorFactory.expressionFactory, policyEvaluatorFactory.defaultXPathCompiler);
                } catch (final IllegalArgumentException e) {
                    throw new IllegalArgumentException(policyEvaluatorFactory.policyMetadata + ": invalid child #" + childIndex + " (CombinerParameters)", e);
                }
                combiningAlgParameters.add(combiningAlgParameter);
            }
        } else if (policyChildElt instanceof PolicySet) {
            final PolicySet childPolicy = (PolicySet) policyChildElt;
            /*
                 * XACML spec §5.1: "ensure that no two policies visible to the PDP have the same identifier"
                 */
            final String childPolicyId = childPolicy.getPolicySetId();
            /*
                 * Create/Update the policySet ref chain if necessary. If policySetRefChainWithArgIffRefTarget is null/empty, this means policyElement is the root policyset (no antecedent), and we
                 * create a chain with its ID, to know the antecedent of the next encountered policyset ref (which may be found deep under multiple levels of nested PolicySets).; else
                 * policySetRefChainWithArgIffRefTarget's last item is either policyElement (iff it is a policy ref's target) or the top-level (as opposed to nested inline) PolicySet that encloses
                 * policyElement, in which either case we already have the info we need in the chain so keep it as is.
                 */
            final Deque<String> newPolicySetRefChain = policySetRefChainWithArgIffRefTarget == null || policySetRefChainWithArgIffRefTarget.isEmpty() ? new ArrayDeque<>(Collections.singletonList(policyId)) : policySetRefChainWithArgIffRefTarget;
            final COMBINED_EVALUATOR childEvaluator = policyEvaluatorFactory.getChildPolicySetEvaluator(childIndex, childPolicy, newPolicySetRefChain);
            combinedEvaluators.add(childEvaluator);
            final COMBINED_EVALUATOR duplicate = childPolicySetEvaluatorsByPolicySetId.putIfAbsent(childPolicyId, childEvaluator);
            if (duplicate != null) {
                throw new IllegalArgumentException("Duplicate PolicySetId = " + childPolicyId);
            }
        } else if (policyChildElt instanceof Policy) {
            final Policy childPolicy = (Policy) policyChildElt;
            /*
                 * XACML spec §5.1: "ensure that no two policies visible to the PDP have the same identifier"
                 */
            final String childPolicyId = childPolicy.getPolicyId();
            final COMBINED_EVALUATOR childEvaluator = policyEvaluatorFactory.getChildPolicyEvaluator(childIndex, childPolicy);
            combinedEvaluators.add(childEvaluator);
            final COMBINED_EVALUATOR duplicate = childPolicyEvaluatorsByPolicyId.putIfAbsent(childPolicyId, childEvaluator);
            if (duplicate != null) {
                throw new IllegalArgumentException("Duplicate PolicyId = " + childPolicyId);
            }
        }
        /*
             * Why isn't there any VariableDefinition in XACML PolicySet defined by OASIS XACML 3.0 spec, like in Policy? If there were, the following code would be used (same as in PolicyEvaluator
             * class).
             */
        // else if (policySetChildElt instanceof VariableDefinition)
        // {
        // final VariableDefinition varDef = (VariableDefinition)
        // policyChildElt;
        // final Deque<String> varDefLongestVarRefChain = new
        // ArrayDeque<>();
        // final VariableReference<?> var;
        // try
        // {
        // var = expressionFactory.addVariable(varDef, defaultXPathCompiler,
        // varDefLongestVarRefChain);
        // } catch (IllegalArgumentException e)
        // {
        // throw new IllegalArgumentException(policyFriendlyId + ": invalid
        // child #" + childIndex + " (VariableDefinition)", e);
        // }
        // 
        // if (var != null)
        // {
        // /*
        // * Conflicts can occur between variables defined in this policy
        // but also with others already in a wider scope, i.e. defined in
        // * parent/ancestor policy
        // */
        // throw new IllegalArgumentException(policyFriendlyId + ":
        // Duplicable VariableDefinition for VariableId=" +
        // var.getVariableId());
        // }
        // 
        // localVariableIds.add(varDef.getVariableId());
        // // check whether the longest VariableReference chain in the
        // VariableDefinition is longer than what we've got so far
        // final int sizeOfVarDefLongestVarRefChain =
        // varDefLongestVarRefChain.size();
        // if(sizeOfVarDefLongestVarRefChain >
        // sizeOfPolicyLongestVarRefChain) {
        // sizeOfPolicyLongestVarRefChain = sizeOfVarDefLongestVarRefChain;
        // }
        // }
        childIndex++;
    }
    /*
         * Why isn't there any VariableDefinition in XACML PolicySet like in Policy? If there were, the final following code would be used: We are done parsing expressions in this policy, including
         * VariableReferences, it's time to remove variables scoped to this policy from the variable manager
         */
    // for (final String varId : variableIds)
    // {
    // expFactory.remove(varId);
    // }
    final ObligationExpressions obligationExps = policyElement.getObligationExpressions();
    final AdviceExpressions adviceExps = policyElement.getAdviceExpressions();
    return policyEvaluatorFactory.getInstance(policyEvaluatorFactory.policyMetadata, targetEvaluator, ImmutableList.of(), policyElement.getPolicyCombiningAlgId(), ImmutableList.copyOf(combinedEvaluators), ImmutableList.copyOf(combiningAlgParameters), obligationExps == null ? null : obligationExps.getObligationExpressions(), adviceExps == null ? null : adviceExps.getAdviceExpressions());
}
Also used : Serializable(java.io.Serializable) BooleanEvaluator(org.ow2.authzforce.core.pdp.impl.BooleanEvaluator) CombiningAlgParameter(org.ow2.authzforce.core.pdp.api.combining.CombiningAlgParameter) JAXBElement(javax.xml.bind.JAXBElement)

Example 2 with VariableReference

use of org.ow2.authzforce.core.pdp.api.expression.VariableReference in project core by authzforce.

the class PolicyEvaluators method getInstance.

/**
 * Creates Policy handler from XACML Policy element
 *
 * @param policyElement              Policy (XACML)
 * @param parentDefaultXPathCompiler XPath compiler corresponding to parent PolicyDefaults/XPathVersion; undefined if this Policy has no parent Policy (root), or none defined in parent, or XPath disabled by PDP configuration
 * @param namespacePrefixToUriMap    namespace prefix-URI mappings from the original XACML Policy (XML) document, to be used for namespace-aware XPath evaluation; empty iff XPath support disabled or: {@code parentDefaultXPathCompiler.isPresent()} and they can be retrieved already from {@code parentDefaultXPathCompiler.get().getDeclaredNamespacePrefixToUriMap()}
 * @param expressionFactory          Expression factory/parser
 * @param combiningAlgRegistry       rule/policy combining algorithm registry
 * @return instance
 * @throws IllegalArgumentException if any argument is invalid
 */
public static StaticTopLevelPolicyElementEvaluator getInstance(final Policy policyElement, final ExpressionFactory expressionFactory, final CombiningAlgRegistry combiningAlgRegistry, final Optional<XPathCompilerProxy> parentDefaultXPathCompiler, final Map<String, String> namespacePrefixToUriMap) throws IllegalArgumentException {
    if (policyElement == null) {
        throw NULL_XACML_POLICY_ARG_EXCEPTION;
    }
    if (expressionFactory == null) {
        throw NULL_EXPRESSION_FACTORY_EXCEPTION;
    }
    if (combiningAlgRegistry == null) {
        throw NULL_XACML_COMBINING_ALG_ARG_EXCEPTION;
    }
    final String policyId = policyElement.getPolicyId();
    final PolicyVersion policyVersion = new PolicyVersion(policyElement.getVersion());
    final PrimaryPolicyMetadata policyMetadata = new BasePrimaryPolicyMetadata(TopLevelPolicyElementType.POLICY, policyId, policyVersion);
    final BooleanEvaluator targetEvaluator = TargetEvaluators.getInstance(policyElement.getTarget(), expressionFactory, parentDefaultXPathCompiler);
    /*
         * Elements defined in xs:choice of XACML schema type PolicyType: Rules/(Rule)CombinerParameters/VariableDefinitions
         */
    final List<Serializable> policyChoiceElements = policyElement.getCombinerParametersAndRuleCombinerParametersAndVariableDefinitions();
    /*
         * There are at most as many combining alg parameters as policyChoiceElements.size().
         */
    final List<CombiningAlgParameter<? extends RuleEvaluator>> combiningAlgParameters = new ArrayList<>(policyChoiceElements.size());
    /*
         * Keep a copy of locally-defined variables defined in this policy, to remove them from the global manager at the end of parsing this policy. They should not be visible outside the scope of
         * this policy. There are at most as many VariableDefinitions as policyChoiceElements.size().
         */
    final List<VariableReference<?>> localVariables = new ArrayList<>(policyChoiceElements.size());
    final DefaultsType policyDefaults = policyElement.getPolicyDefaults();
    Optional<XPathCompilerProxy> childXpathCompiler;
    /*
         * Leave childXpathCompiler undefined if XPath support disabled globally.
         *
         * Else (XPath support enabled globally, but may be disabled locally for this specific Policy if XPathVersion undefined in it and any enclosing PolicySet)...
         * Reminder: According to the XACML standard, the Policy(Set)Defaults/XPathVersion must be specified (non-null) in the current Policy(Set) or any of its enclosing/ancestor PolicySet for XPath expressions to be allowed (therefore a need for a XPathCompiler), e.g. in AttributeSelectors, XPath functions, etc.
         */
    if (expressionFactory.isXPathEnabled()) {
        /*
                If both policyDefaults and parentDefaultXPathCompiler undefined, it means no Policy(Set)Defaults/XPathVersion defined (in current Policy and any enclosing PolicySet), i.e. XPath support is disabled for this Policy, so leave childXpathCompiler undefined like parentDefaultXPathCompiler.

                We may reuse parentDefaultXPathCompiler if:
                 - parentDefaultXPathCompiler is defined
                 - AND policyDefaults/XPathVersion is undefined OR the XPath version matches the policyDefaults/XPathVersion
                 - AND namespacePrefixToUriMap is empty (i.e. only the ones from parentDefaultXPathCompiler apply)
                 */
        if (policyDefaults == null) {
            if (parentDefaultXPathCompiler.isEmpty() || namespacePrefixToUriMap.isEmpty()) {
                childXpathCompiler = parentDefaultXPathCompiler;
            } else {
                // parentDefaultXPathCompiler defined AND namespacePrefixToUriMap not empty -> new XPathCompiler to handle these new namespacePrefixToUriMap map
                childXpathCompiler = Optional.of(new ImmutableXPathCompiler(parentDefaultXPathCompiler.get().getXPathVersion(), namespacePrefixToUriMap, List.of()));
            }
        } else {
            // policyDefaults defined
            final String xpathVersionUri = policyDefaults.getXPathVersion();
            assert xpathVersionUri != null : "PolicyDefaults(non-null)/XPathVersion = null, which violates the XACML schema! Fix: enforce XACML schema validation.";
            try {
                final XPathVersion xPathVersion = XPathVersion.fromURI(xpathVersionUri);
                if (parentDefaultXPathCompiler.isEmpty()) {
                    childXpathCompiler = Optional.of(new ImmutableXPathCompiler(xPathVersion, namespacePrefixToUriMap, List.of()));
                } else // parentDefaultXPathCompiler defined, re-use it only if XPath version matches policyDefaults and namespacePrefixToUriMap empty
                if (parentDefaultXPathCompiler.get().getXPathVersion().equals(xPathVersion) && namespacePrefixToUriMap.isEmpty()) {
                    childXpathCompiler = parentDefaultXPathCompiler;
                } else {
                    childXpathCompiler = Optional.of(new ImmutableXPathCompiler(xPathVersion, namespacePrefixToUriMap, List.of()));
                }
            } catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException(policyMetadata + ": Invalid PolicySetDefaults/XPathVersion or XML namespace prefix/URI undefined", e);
            }
        }
    } else {
        // XPath support disabled globally
        childXpathCompiler = Optional.empty();
    }
    /*
        childXpathCompiler is empty iff XPath support disabled globally (!expressionFactory.isXPathEnabled()) OR (policyDefaults ==null AND parentDefaultXPathCompiler.isEmpty()), in other words iff XPath support disabled for this Policy
         */
    /*
		 If XPath support enabled, we can reuse the same XPathCompiler as long as there is no new VariableDefinition
		 */
    boolean isNewChildXpathCompilerRequired = false;
    /*
         * We keep a record of the size of the longest chain of VariableReference in this policy, and update it when a VariableDefinition occurs
         */
    int sizeOfPolicyLongestVarRefChain = 0;
    /*
         * Map to get rules by their ID so that we can resolve rules associated with RuleCombinerParameters, and detect duplicate RuleId. We want to preserve insertion order, to get map.values() in
         * order of declaration, so that ordered-* algorithms have rules in order. There are at most as many Rules as policyChoiceElements.size().
         */
    final Map<String, RuleEvaluator> ruleEvaluatorsByRuleIdInOrderOfDeclaration = new LinkedHashMap<>(policyChoiceElements.size());
    int childIndex = 0;
    for (final Serializable policyChildElt : policyChoiceElements) {
        /*
				 If and only if XPath enabled for this Policy (childXpathCompiler.isPresent()), XPath compiler needed for each child, can we reuse the same one as last time (it was used to create a child element evaluator) ?
				 */
        if (childXpathCompiler.isPresent() && isNewChildXpathCompilerRequired) {
            /*
					 New Variables defined since last XPath compiler created -> we need to use a new one to handle the new XACML Variables as XPath variables
					 */
            childXpathCompiler = Optional.of(new ImmutableXPathCompiler(childXpathCompiler.get().getXPathVersion(), namespacePrefixToUriMap, localVariables));
            isNewChildXpathCompilerRequired = false;
        }
        if (policyChildElt instanceof RuleCombinerParameters) {
            final String combinedRuleId = ((RuleCombinerParameters) policyChildElt).getRuleIdRef();
            final RuleEvaluator ruleEvaluator = ruleEvaluatorsByRuleIdInOrderOfDeclaration.get(combinedRuleId);
            if (ruleEvaluator == null) {
                throw new IllegalArgumentException(policyMetadata + ":  invalid RuleCombinerParameters: referencing undefined child Rule #" + combinedRuleId + " (no such rule defined before this element)");
            }
            final BaseCombiningAlgParameter<RuleEvaluator> combiningAlgParameter;
            try {
                combiningAlgParameter = new BaseCombiningAlgParameter<>(ruleEvaluator, ((CombinerParametersType) policyChildElt).getCombinerParameters(), expressionFactory, childXpathCompiler);
            } catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException(policyMetadata + ": invalid child #" + childIndex + " (RuleCombinerParameters)", e);
            }
            combiningAlgParameters.add(combiningAlgParameter);
        } else if (policyChildElt instanceof CombinerParametersType) {
            /*
                 * CombinerParameters that is not RuleCombinerParameters already tested before
                 */
            final BaseCombiningAlgParameter<RuleEvaluator> combiningAlgParameter;
            try {
                combiningAlgParameter = new BaseCombiningAlgParameter<>(null, ((CombinerParametersType) policyChildElt).getCombinerParameters(), expressionFactory, childXpathCompiler);
            } catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException(policyMetadata + ": invalid child #" + childIndex + " (CombinerParameters)", e);
            }
            combiningAlgParameters.add(combiningAlgParameter);
        } else if (policyChildElt instanceof VariableDefinition) {
            final VariableDefinition varDef = (VariableDefinition) policyChildElt;
            final Deque<String> varDefLongestVarRefChain = new ArrayDeque<>();
            final VariableReference<?> var;
            try {
                var = expressionFactory.addVariable(varDef, varDefLongestVarRefChain, childXpathCompiler);
            } catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException(policyMetadata + ": invalid child #" + childIndex + " (VariableDefinition)", e);
            }
            if (var != null) {
                /*
                     * Conflicts can occur between variables defined in this policy but also with others already in a wider scope, i.e. defined in parent/ancestor policy
                     */
                throw new IllegalArgumentException(policyMetadata + ": Duplicable VariableDefinition for VariableId = " + var.getVariableId());
            }
            localVariables.add(expressionFactory.getVariableExpression(varDef.getVariableId()));
            /*
					 New Variables defined since last XPath compiler created -> we need to use a new one to handle the new XACML Variables as XPath variables in the subsequent child elements
					 */
            isNewChildXpathCompilerRequired = true;
            /*
                 * check whether the longest VariableReference chain in the VariableDefinition is longer than what we've got so far
                 */
            final int sizeOfVarDefLongestVarRefChain = varDefLongestVarRefChain.size();
            if (sizeOfVarDefLongestVarRefChain > sizeOfPolicyLongestVarRefChain) {
                sizeOfPolicyLongestVarRefChain = sizeOfVarDefLongestVarRefChain;
            }
        } else if (policyChildElt instanceof Rule) {
            final RuleEvaluator ruleEvaluator;
            try {
                ruleEvaluator = new RuleEvaluator((Rule) policyChildElt, expressionFactory, childXpathCompiler);
            } catch (final IllegalArgumentException e) {
                throw new IllegalArgumentException(policyMetadata + ": Error parsing child #" + childIndex + " (Rule)", e);
            }
            final RuleEvaluator conflictingRuleEvaluator = ruleEvaluatorsByRuleIdInOrderOfDeclaration.putIfAbsent(ruleEvaluator.getRuleId(), ruleEvaluator);
            if (conflictingRuleEvaluator != null) {
                /*
                     * Conflict: 2 Rule elements with same RuleId -> violates uniqueness of RuleId within a Policy (XACML spec)
                     */
                throw new IllegalArgumentException(policyMetadata + ": Duplicate Rule with RuleId = " + conflictingRuleEvaluator.getRuleId());
            }
        }
        childIndex++;
    }
    final ObligationExpressions obligationExps = policyElement.getObligationExpressions();
    final AdviceExpressions adviceExps = policyElement.getAdviceExpressions();
    final StaticTopLevelPolicyElementEvaluator policyEvaluator = new StaticBaseTopLevelPolicyElementEvaluator<>(RuleEvaluator.class, policyMetadata, Optional.empty(), targetEvaluator, ImmutableList.copyOf(localVariables), policyElement.getRuleCombiningAlgId(), ImmutableList.copyOf(ruleEvaluatorsByRuleIdInOrderOfDeclaration.values()), ImmutableList.copyOf(combiningAlgParameters), obligationExps == null ? null : obligationExps.getObligationExpressions(), adviceExps == null ? null : adviceExps.getAdviceExpressions(), expressionFactory, combiningAlgRegistry, childXpathCompiler);
    /*
         * We are done parsing expressions in this policy, including VariableReferences, it's time to remove variables scoped to this policy from the variable manager
         */
    localVariables.forEach(var -> expressionFactory.removeVariable(var.getVariableId()));
    return policyEvaluator;
}
Also used : Serializable(java.io.Serializable) BaseXPathCompilerProxy(org.ow2.authzforce.core.pdp.api.expression.BaseXPathCompilerProxy) XPathCompilerProxy(org.ow2.authzforce.core.pdp.api.expression.XPathCompilerProxy) BooleanEvaluator(org.ow2.authzforce.core.pdp.impl.BooleanEvaluator) CombiningAlgParameter(org.ow2.authzforce.core.pdp.api.combining.CombiningAlgParameter) VariableReference(org.ow2.authzforce.core.pdp.api.expression.VariableReference) RuleEvaluator(org.ow2.authzforce.core.pdp.impl.rule.RuleEvaluator) XPathVersion(org.ow2.authzforce.xacml.identifiers.XPathVersion)

Example 3 with VariableReference

use of org.ow2.authzforce.core.pdp.api.expression.VariableReference in project core-pdp-api by authzforce.

the class XPathValue method evaluate.

/**
 * Convenient method to get the XML nodes ("node-set") matching the XPath expression from the Content node of the XACML Attributes element with category <i>XPathCategory</i> in this
 * {@code context}. <i>XPathCategory</i> is extracted from the attribute of the same name in {@code otherXmlAttributes} argument passed to {@link #XPathValue(String, Map, XPathCompilerProxy)} when
 * creating this instance. To be used by XPath-based functions defined in section A.3.15 of XACML 3.0 Core specification.
 *
 * @param context
 *            current evaluation context
 * @return node-set
 * @throws org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException
 *             error evaluating the XPath expression
 */
public XdmValue evaluate(final EvaluationContext context) throws IndeterminateEvaluationException {
    if (context == null) {
        throw this.missingContextException;
    }
    final XdmNode contentNode = context.getAttributesContent(this.xpathCategory);
    if (contentNode == null) {
        throw this.missingAttributesContentException;
    }
    /*
		 * An XPathExecutable is immutable, and therefore thread-safe. It is simpler to load a new XPathSelector each time the expression is to be evaluated. However, the XPathSelector is serially
		 * reusable within a single thread. See Saxon Javadoc.
		 */
    final XPathSelector xpathSelector = xPathEvaluator.load();
    try {
        for (final VariableReference<?> xpathVar : xpathVariables) {
            final Value val = context.getVariableValue(xpathVar.getVariableId(), xpathVar.getReturnType());
            xpathSelector.setVariable(xpathVar.getXPathVariableName(), val.getXdmValue());
        }
        xpathSelector.setContextItem(contentNode);
        return xpathSelector.evaluate();
    } catch (final SaxonApiException e) {
        throw new IndeterminateEvaluationException(this.xpathEvalExceptionStatus, e);
    }
}
Also used : IndeterminateEvaluationException(org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException)

Aggregations

Serializable (java.io.Serializable)2 CombiningAlgParameter (org.ow2.authzforce.core.pdp.api.combining.CombiningAlgParameter)2 BooleanEvaluator (org.ow2.authzforce.core.pdp.impl.BooleanEvaluator)2 JAXBElement (javax.xml.bind.JAXBElement)1 IndeterminateEvaluationException (org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException)1 BaseXPathCompilerProxy (org.ow2.authzforce.core.pdp.api.expression.BaseXPathCompilerProxy)1 VariableReference (org.ow2.authzforce.core.pdp.api.expression.VariableReference)1 XPathCompilerProxy (org.ow2.authzforce.core.pdp.api.expression.XPathCompilerProxy)1 RuleEvaluator (org.ow2.authzforce.core.pdp.impl.rule.RuleEvaluator)1 XPathVersion (org.ow2.authzforce.xacml.identifiers.XPathVersion)1