/// <summary> /// Evaluates the variable into a value. /// </summary> /// <param name="context">The contex of the evaluation.</param> /// <returns>The value of the function.</returns> public EvaluationValue Evaluate(EvaluationContext context) { if (context == null) { throw new ArgumentNullException("context"); } context.Trace("Evaluating variable"); context.AddIndent(); try { if (_variableDefinition.Expression is pol.ApplyElement) { context.Trace("Apply within condition."); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. Apply _childApply = new Apply((pol.ApplyElement)_variableDefinition.Expression); // Evaluate the Apply _value = _childApply.Evaluate(context); context.TraceContextValues(); return(_value); } else if (_variableDefinition.Expression is pol.FunctionElement) { throw new NotImplementedException("FunctionElement"); //TODO: } else if (_variableDefinition.Expression is pol.VariableReferenceElement) { pol.VariableReferenceElement variableRef = _variableDefinition.Expression as pol.VariableReferenceElement; VariableDefinition variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; context.TraceContextValues(); if (!variableDef.IsEvaluated) { return(variableDef.Evaluate(context)); } else { return(variableDef.Value); } } else if (_variableDefinition.Expression is pol.AttributeValueElementReadWrite) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", _variableDefinition.Expression.ToString()); pol.AttributeValueElementReadWrite att = (pol.AttributeValueElementReadWrite)_variableDefinition.Expression; pol.AttributeValueElement attributeValue = new pol.AttributeValueElement(att.DataType, att.Contents, att.SchemaVersion); _value = new EvaluationValue( attributeValue.GetTypedValue(attributeValue.GetType(context), 0), attributeValue.GetType(context)); return(_value); } else if (_variableDefinition.Expression is pol.AttributeDesignatorBase) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", _variableDefinition.Expression.ToString()); pol.AttributeDesignatorBase attrDes = (pol.AttributeDesignatorBase)_variableDefinition.Expression; BagValue bag = EvaluationEngine.Resolve(context, attrDes); // If the attribute was not resolved by the EvaluationEngine search the // attribute in the context document, also using the EvaluationEngine public // methods. if (bag.BagSize == 0) { if (_variableDefinition.Expression is pol.SubjectAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding subject attribute designator: {0}", attrib.ToString()); bag.Add(attrib); } } else if (_variableDefinition.Expression is pol.ResourceAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding resource attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (_variableDefinition.Expression is pol.ActionAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding action attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (_variableDefinition.Expression is pol.EnvironmentAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding environment attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } } // If the argument was not found and the attribute must be present this is // a MissingAttribute situation so set the flag. Otherwise add the attribute // to the processed arguments. if (bag.BagSize == 0 && attrDes.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(attrDes); _value = EvaluationValue.Indeterminate; } else { _value = new EvaluationValue(bag, bag.GetType(context)); } return(_value); } else if (_variableDefinition.Expression is pol.AttributeSelectorElement) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { pol.AttributeSelectorElement attributeSelector = (pol.AttributeSelectorElement)_variableDefinition.Expression; BagValue bag = EvaluationEngine.Resolve(context, attributeSelector); if (bag.Elements.Count == 0 && attributeSelector.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(attributeSelector); _value = EvaluationValue.Indeterminate; } else { _value = new EvaluationValue(bag, bag.GetType(context)); } } catch (EvaluationException e) { context.Trace("ERR: {0}", e.Message); context.ProcessingError = true; _value = EvaluationValue.Indeterminate; } return(_value); } throw new NotSupportedException("internal error"); } finally { _isEvaluated = true; context.RemoveIndent(); } }
/// <summary> /// Evaluates the target items and return wether the target applies to the context or not. /// </summary> /// <param name="context">The evaluation context instance.</param> /// <param name="targetItem">The target item in the context document.</param> /// <returns></returns> public virtual TargetEvaluationValue Evaluate(EvaluationContext context, ctx.TargetItemBase targetItem) { if (context == null) { throw new ArgumentNullException("context"); } if (_targetItems.IsAny) { context.Trace("IsAny"); return(TargetEvaluationValue.Match); } _evaluationValue = TargetEvaluationValue.NoMatch; //Match TargetItem foreach (TargetItemBase polItem in _targetItems.ItemsList) { foreach (TargetMatchBase match in polItem.Match) { _evaluationValue = TargetEvaluationValue.NoMatch; context.Trace("Using function: {0}", match.MatchId); IFunction matchFunction = EvaluationEngine.GetFunction(match.MatchId); if (matchFunction == null) { context.Trace("ERR: function not found {0}", match.MatchId); context.ProcessingError = true; return(TargetEvaluationValue.Indeterminate); } else if (matchFunction.Returns == null) { // Validates the function return value context.Trace("ERR: The function '{0}' does not defines it's return value", match.MatchId); context.ProcessingError = true; return(TargetEvaluationValue.Indeterminate); } else if (matchFunction.Returns != DataTypeDescriptor.Boolean) { context.Trace("ERR: Function does not return Boolean a value"); context.ProcessingError = true; return(TargetEvaluationValue.Indeterminate); } else { Context.AttributeElement attribute = EvaluationEngine.Resolve(context, match, targetItem); if (attribute != null) { context.Trace("Attribute found, evaluating match function"); try { EvaluationValue returnValue = EvaluationEngine.EvaluateFunction(context, matchFunction, match.AttributeValue, attribute); _evaluationValue = returnValue.BoolValue ? TargetEvaluationValue.Match : TargetEvaluationValue.NoMatch; } catch (EvaluationException e) { context.Trace("ERR: {0}", e.Message); _evaluationValue = TargetEvaluationValue.Indeterminate; } } // Validate MustBePresent if (match.AttributeReference.MustBePresent) { if (context.IsMissingAttribute) { context.Trace("Attribute not found and must be present"); _evaluationValue = TargetEvaluationValue.Indeterminate; } } if (context.ProcessingError) { _evaluationValue = TargetEvaluationValue.Indeterminate; } // Do not iterate if the value was found if (_evaluationValue != TargetEvaluationValue.Match) { break; } } } // Do not iterate if the value was found if (_evaluationValue == TargetEvaluationValue.Match) { return(_evaluationValue); } } return(_evaluationValue); }
/// <summary> /// THe argument processing method resolves all the attribute designators, attribute /// selectors. If there is an internal Apply it will be evaulated within this method. /// </summary> /// <remarks>All the processed arguments are converted into an IFunctionParameter instance /// because this is the only value that can be used to call a function.</remarks> /// <param name="context">The evaluation context instance.</param> /// <param name="arguments">The arguments to process.</param> /// <returns>A list of arguments ready to be used by a function.</returns> private FunctionParameterCollection ProcessArguments(EvaluationContext context, ExpressionCollection arguments) { context.Trace("Processing arguments"); context.AddIndent(); // Create a list to return the processed values. var processedArguments = new FunctionParameterCollection(); // Iterate through the arguments, the IExpressionType is a mark interface foreach (IExpression arg in arguments) { var apply = arg as ApplyElement; if (apply != null) { context.Trace("Nested apply"); // There is a nested apply un this policy a new Apply will be created and also // evaluated. It's return value will be used as the processed argument. var childApply = new Apply(apply); // Evaluate the Apply EvaluationValue retVal = childApply.Evaluate(context); context.TraceContextValues(); // If the results were Indeterminate the Indeterminate value will be placed in // the processed arguments, later another method will validate the parameters // and cancel the evaluation propperly. if (!retVal.IsIndeterminate) { if (!context.IsMissingAttribute) { processedArguments.Add(retVal); } } else { processedArguments.Add(retVal); } } else { var write = arg as FunctionElementReadWrite; if (write != null) { // Search for the function and place it in the processed arguments. var functionId = new FunctionElement(write.FunctionId, write.SchemaVersion); context.Trace("Function {0}", functionId.FunctionId); IFunction function = EvaluationEngine.GetFunction(functionId.FunctionId); if (function == null) { context.Trace("ERR: function not found {0}", _applyBase.FunctionId); context.ProcessingError = true; processedArguments.Add(EvaluationValue.Indeterminate); } else { processedArguments.Add(function); } } else if (arg is VariableReferenceElement) { var variableRef = arg as VariableReferenceElement; var variableDef = context.CurrentPolicy.VariableDefinition[variableRef.VariableId] as VariableDefinition; context.TraceContextValues(); Debug.Assert(variableDef != null, "variableDef != null"); processedArguments.Add(!variableDef.IsEvaluated ? variableDef.Evaluate(context) : variableDef.Value); } else { var readWrite = arg as AttributeValueElementReadWrite; if (readWrite != null) { // The AttributeValue does not need to be processed context.Trace("Attribute value {0}", arg.ToString()); processedArguments.Add(new AttributeValueElement(readWrite.DataType, readWrite.Contents, readWrite.SchemaVersion)); } else { var des = arg as AttributeDesignatorBase; if (des != null) { // Resolve the AttributeDesignator using the EvaluationEngine public methods. context.Trace("Processing attribute designator: {0}", arg.ToString()); var attrDes = des; BagValue bag = EvaluationEngine.Resolve(context, attrDes); // If the attribute was not resolved by the EvaluationEngine search the // attribute in the context document, also using the EvaluationEngine public // methods. if (bag.BagSize == 0) { if (arg is SubjectAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding subject attribute designator: {0}", attrib.ToString()); bag.Add(attrib); break; } } else if (arg is ResourceAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding resource attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (arg is ActionAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding action attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } else if (arg is EnvironmentAttributeDesignatorElement) { ctx.AttributeElement attrib = EvaluationEngine.GetAttribute(context, attrDes); if (attrib != null) { context.Trace("Adding environment attribute designator {0}", attrib.ToString()); bag.Add(attrib); } } } // If the argument was not found and the attribute must be present this is // a MissingAttribute situation so set the flag. Otherwise add the attribute // to the processed arguments. if (bag.BagSize == 0 && attrDes.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(attrDes); } else { processedArguments.Add(bag); } } else { var @base = arg as AttributeSelectorElement; if (@base != null) { // Resolve the XPath query using the EvaluationEngine public methods. context.Trace("Attribute selector"); try { BagValue bag = EvaluationEngine.Resolve(context, @base); if (bag.Elements.Count == 0 && @base.MustBePresent) { context.Trace("Attribute is missing"); context.IsMissingAttribute = true; context.AddMissingAttribute(@base); } else { processedArguments.Add(bag); } } catch (EvaluationException e) { context.Trace("ERR: {0}", e.Message); processedArguments.Add(EvaluationValue.Indeterminate); context.ProcessingError = true; } } } } } } } context.RemoveIndent(); return(processedArguments); }
/// <summary> /// Creates a new runtime policy set evaluation. /// </summary> /// <param name="engine">The evaluation engine.</param> /// <param name="policySet">The policy set defined in the policy document.</param> public PolicySet(EvaluationEngine engine, PolicySetElement policySet) { if (engine == null) { throw new ArgumentNullException("engine"); } if (policySet == null) { throw new ArgumentNullException("policySet"); } _policySet = policySet; // Create a runtime target of this policy set. if (policySet.Target != null) { _target = new Target((TargetElement)policySet.Target); foreach (ResourceElement resource in policySet.Target.Resources.ItemsList) { foreach (ResourceMatchElement rmatch in resource.Match) { if (!_allResources.Contains(rmatch.AttributeValue.Contents)) { _allResources.Add(rmatch.AttributeValue.Contents); } } } } // Add all the policies (or policy set) inside this policy set. foreach (object child in policySet.Policies) { var childPolicySet = child as PolicySetElement; var childPolicyElement = child as PolicyElement; var childPolicySetIdReference = child as PolicySetIdReferenceElement; var childPolicyIdReferenceElement = child as PolicyIdReferenceElement; if (childPolicySet != null) { var policySetEv = new PolicySet(engine, childPolicySet); foreach (string rName in policySetEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policySetEv); } else if (childPolicyElement != null) { var policyEv = new Policy(childPolicyElement); foreach (string rName in policyEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policyEv); } else if (childPolicySetIdReference != null) { PolicySetElement policySetDefinition = EvaluationEngine.Resolve(childPolicySetIdReference); if (policySetDefinition != null) { var policySetEv = new PolicySet(engine, policySetDefinition); foreach (string rName in policySetEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policySetEv); } else { throw new EvaluationException(string.Format(Properties.Resource.exc_policyset_reference_not_resolved, ((PolicySetIdReferenceElement)child).PolicySetId)); } } else if (childPolicyIdReferenceElement != null) { PolicyElement policyDefinition = EvaluationEngine.Resolve(childPolicyIdReferenceElement); if (policyDefinition != null) { var policyEv = new Policy(policyDefinition); foreach (string rName in policyEv.AllResources) { if (!_allResources.Contains(rName)) { _allResources.Add(rName); } } _policies.Add(policyEv); } else { throw new EvaluationException(string.Format(Properties.Resource.exc_policy_reference_not_resolved, ((PolicyIdReferenceElement)child).PolicyId)); } } } }