http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java new file mode 100755 index 0000000..e61e59f --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagIsIn.java @@ -0,0 +1,132 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.util.Iterator; +import java.util.List; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionBagIsIn implements {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to + * implement the XACML 'type'-is-in predicates as functions taking two arguments, the first of <code>type</code> and the second of type <code>Bag</code>, + * and returning a <code>Boolean</code> for whether the first argument is contained in the second. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * string-is-in + * boolean-is-in + * integer-is-in + * double-is-in + * time-is-in + * date-is-in + * dateTime-is-in + * anyURI-is-in + * hexBinary-is-in + * base64Binary-is-in + * dayTimeDuration-is-in (version 1 and3) + * yearMonthDuration-is-in (version 1 and 3) + * x500Name-is-in + * rfc822Name-is-in + * ipAddress-is-in + * dnsName-is-in + * + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + * @param <I> the java class for the data type of the elements in the Input argument Bag + * + * The Output for these functions is always a Boolean. + */ +public class FunctionDefinitionBagIsIn<I> extends FunctionDefinitionBase<Boolean, I> { + + + /** + * Constructor - need dataType input because of java Generic type-erasure during compilation. + * + * @param idIn + * @param dataTypeArgsIn + */ + public FunctionDefinitionBagIsIn(Identifier idIn, DataType<I> dataTypeArgsIn) { + super(idIn, DataTypes.DT_BOOLEAN, dataTypeArgsIn, false); + + } + + /** + * Evaluates this <code>FunctionDefinition</code> on the given <code>List</code> of{@link com.att.research.xacmlatt.pdp.policy.FunctionArgument}s. + * + * @param evaluationContext the {@link com.att.research.xacmlatt.pdp.eval.EvaluationContext} to use in the evaluation + * @param arguments the <code>List</code> of <code>FunctionArgument</code>s for the evaluation + * @return an {@link com.att.research.xacmlatt.pdp.policy.ExpressionResult} with the results of the call + */ + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + if (arguments == null || arguments.size() != 2) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Expected 2 arguments, got " + + ((arguments == null) ? "null" : arguments.size()) )); + } + + // get the thing to look for in the bag + FunctionArgument elementArgument = arguments.get(0); + + ConvertedArgument<I> convertedTargetArgument = new ConvertedArgument<I>(elementArgument, this.getDataTypeArgs(), false); + if ( ! convertedTargetArgument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedTargetArgument.getStatus())); + } + + // Special case: Most methods want the value contained in the AttributeValue object inside the FunctionArgument. + // This one wants the AttributeValue itself. + // We use the ConvertedArgument constructor to validate that the argument is ok, then use the AttributeValue + // from the FunctionArgument. + AttributeValue<?> attributeValueElement = elementArgument.getValue(); + + // now get the bag + FunctionArgument bagArgument = arguments.get(1); + ConvertedArgument<Bag> convertedBagArgument = new ConvertedArgument<Bag>(bagArgument, null, true); + + if ( ! convertedBagArgument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedBagArgument.getStatus())); + } + + Bag bag = convertedBagArgument.getBag(); + + Iterator<AttributeValue<?>> iterBagContents = bag.getAttributeValues(); + while (iterBagContents.hasNext()) { + AttributeValue<?> attributeValueBagContents = iterBagContents.next(); + + /* + * Should we be checking the type of the bag contents and returning an error if the bag contents are not of the + * right type? The spec does not say this, so we just use the AttributeValue.equals() method for now. + */ + if (attributeValueElement.equals(attributeValueBagContents)) { + return ER_TRUE; + } + } + + return ER_FALSE; + } + + + + +}
http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java new file mode 100755 index 0000000..03e1210 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagOneAndOnly.java @@ -0,0 +1,117 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.util.List; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionBagOneAndOnly implements {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to + * implement the XACML 'type'-one-and-only predicates as functions taking one <code>Bag</code> argument and returning the single element in that bag of the 'type'. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * string-one-and-only + * boolean-one-and-only + * integer-one-and-only + * double-one-and-only + * time-one-and-only + * date-one-and-only + * dateTime-one-and-only + * anyURI-one-and-only + * hexBinary-one-and-only + * base64Binary-one-and-only + * dayTimeDuration-one-and-only (version 1 and3) + * yearMonthDuration-one-and-only (version 1 and 3) + * x500Name-one-and-only + * rfc822Name-one-and-only + * ipAddress-one-and-only + * dnsName-one-and-only + * + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + * @param <I> the java class for the data type of the elements in the bag handed to this as the Input argument, + * which is also the type of the return value + * + */ +public class FunctionDefinitionBagOneAndOnly<I> extends FunctionDefinitionBase<I,I> { + + + /** + * Constructor - need dataType input because of java Generic type-erasure during compilation. + * + * @param idIn + * @param dataTypeArgsIn + */ + public FunctionDefinitionBagOneAndOnly(Identifier idIn, DataType<I> dataTypeArgsIn) { + super(idIn, dataTypeArgsIn, dataTypeArgsIn, false); + } + + /** + * Evaluates this <code>FunctionDefinition</code> on the given <code>List</code> of{@link com.att.research.xacmlatt.pdp.policy.FunctionArgument}s. + * + * @param evaluationContext the {@link com.att.research.xacmlatt.pdp.eval.EvaluationContext} to use in the evaluation + * @param arguments the <code>List</code> of <code>FunctionArgument</code>s for the evaluation + * @return an {@link com.att.research.xacmlatt.pdp.policy.ExpressionResult} with the results of the call + */ + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + if (arguments == null || arguments.size() != 1) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + " Expected 1 argument, got " + + ((arguments == null) ? "null" : arguments.size()) )); + } + + FunctionArgument argument = arguments.get(0); + ConvertedArgument<Bag> convertedArgument = new ConvertedArgument<Bag>(argument, null, true); + + if ( ! convertedArgument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedArgument.getStatus())); + } + + Bag bag = convertedArgument.getBag(); + + if (bag.size() != 1) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + + " Expected 1 but Bag has " + bag.size() + " elements")); + } + + // get the single value from the bag + AttributeValue<?> attributeValueOneAndOnly = bag.getAttributeValues().next(); + assert(attributeValueOneAndOnly != null); + + // make sure it has the right type + // + if (!this.getDataTypeId().equals(attributeValueOneAndOnly.getDataTypeId())) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + + " Element in bag of wrong type. Expected " + + this.getShortDataTypeId(this.getDataTypeId()) + " got " + this.getShortDataTypeId(attributeValueOneAndOnly.getDataTypeId()))); + } + return ExpressionResult.newSingle(attributeValueOneAndOnly); + } + + + + + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java new file mode 100755 index 0000000..af75491 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBagSize.java @@ -0,0 +1,110 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.math.BigInteger; +import java.util.List; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.XACML; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionBagSize implements {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to + * implement the XACML 'type'-bag-size predicates as functions taking one <code>Bag</code> argument and returning an <code>Integer</code> + * representing the number of elements in the bag. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * string-bag-size + * boolean-bag-size + * integer-bag-size + * double-bag-size + * time-bag-size + * date-bag-size + * dateTime-bag-size + * anyURI-bag-size + * hexBinary-bag-size + * base64Binary-bag-size + * dayTimeDuration-bag-size (version 1 and3) + * yearMonthDuration-bag-size (version 1 and 3) + * x500Name-bag-size + * rfc822Name-bag-size + * ipAddress-bag-size + * dnsName-bag-size + * + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + * @param <I> the java class for the data type of the function Input arguments + */ +public class FunctionDefinitionBagSize<I> extends FunctionDefinitionBase<BigInteger, I> { + + + /** + * Constructor - need dataType input because of java Generic type-erasure during compilation. + * + * @param idIn + * @param dataTypeArgsIn + */ + public FunctionDefinitionBagSize(Identifier idIn, DataType<I> dataTypeArgsIn) { + super(idIn, DataTypes.DT_INTEGER, dataTypeArgsIn, false); + } + + /** + * Evaluates this <code>FunctionDefinition</code> on the given <code>List</code> of{@link com.att.research.xacmlatt.pdp.policy.FunctionArgument}s. + * + * @param evaluationContext the {@link com.att.research.xacmlatt.pdp.eval.EvaluationContext} to use in the evaluation + * @param arguments the <code>List</code> of <code>FunctionArgument</code>s for the evaluation + * @return an {@link com.att.research.xacmlatt.pdp.policy.ExpressionResult} with the results of the call + */ + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + if (arguments == null || arguments.size() != 1) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Expected 1 argument, got " + + ((arguments == null) ? "null" : arguments.size()) )); + } + + FunctionArgument argument = arguments.get(0); + ConvertedArgument<Bag> convertedArgument = new ConvertedArgument<Bag>(argument, null, true); + + if ( ! convertedArgument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedArgument.getStatus())); + } + + Bag bag = convertedArgument.getBag(); + + if (bag == null) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Bag is null" )); + + } + + + // type is correct, so create a wrapper and return it + AttributeValue<BigInteger> resultAttributeValue = new StdAttributeValue<BigInteger>(XACML.ID_DATATYPE_INTEGER, BigInteger.valueOf(bag.size())); + return ExpressionResult.newSingle(resultAttributeValue); + } + + + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java new file mode 100755 index 0000000..390e9b2 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionBase.java @@ -0,0 +1,165 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.datatypes.DataTypeBoolean; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinition; + + +/** + * /** + * FunctionDefinitionBase provides a common base for {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition}s. + * The child classes derived from this are of two types: + * <UL> + * <LI> Functions returning a single simple value of a type defined in {@link com.att.research.xacml.std.datatypes.DataTypes}. + * These functions will all derive from {@link com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionSimple}. + * <LI> Functions returning a single bag with elements of a single type. + * <UL> + * <P> + * This base class contains the following components: + * <UL> + * <LI> The Identity for this function. + * <LI> The DataType of the data returned from this function. + * For Bags this means the DataType of the elements in the bag, or null if that is ambiguous. + * <LI> Commonly-used values. + * </UL> + * + * @author glenngriffin + * + * @param <O> the java class for the Output data type returned by the <code>FunctionDefinition</code> + * @param <I> the java class for the Input data type expected in the arguments to the <code>FunctionDefinition</code>. + * Some functions have non-homogeneous arguments but may still have a main 'type'. + */ +public abstract class FunctionDefinitionBase<O,I> implements FunctionDefinition { + + // The XACML identifier string for this particular function + private Identifier id; + + // each function derived from this returns a single non-bag data value of the following type, or a Bag containing elements of this type + private DataType<O> dataTypeReturn; + + // All functions have input arguments and expect them to be of a given type. + // In some instances the argument gets multiple values of different types, but when the function has a 'type' associated with it's name + // specific ones of the input must be of this type. + // When an argument Input to the function is a Bag, the elements in that bag will be of this type. + // This corresponds most closely to the 'type' in the function name (as in 'type'-bag or 'type'-equals). + private DataType<I> dataTypeArgs; + + // true = the return value from this function is a bag; false = return value is a single-value DataType object + private boolean returnsBag; + + /* + * For functions that return a Boolean result we create a single instance of the True/False return values that they can share + */ + protected static final ExpressionResult ER_TRUE = ExpressionResult.newSingle(DataTypeBoolean.AV_TRUE); + protected static final ExpressionResult ER_FALSE = ExpressionResult.newSingle(DataTypeBoolean.AV_FALSE); + + /** + * Creates a new <code>FunctionDefinitionBase</code> with the {@link com.att.research.xacml.api.Identifier} <code>idIn</code> as + * the function id. + * + * @param idIn the <code>Identifier</code> for this <code>FunctionDefinitionBase</code> + */ + protected FunctionDefinitionBase(Identifier idIn, DataType<O> returnDataTypeIn, DataType<I> argumentDataTypeIn, boolean returnsBagIn) { + this.id = idIn; + this.dataTypeReturn = returnDataTypeIn; + this.dataTypeArgs = argumentDataTypeIn; + this.returnsBag = returnsBagIn; + } + + /** + * Returns a shortened version of the Id for this function, primarilly for use with error messages to prevent them from becoming too long. + * This is a simple convenience method to reduce code bloat. + * + * @return + */ + public String getShortFunctionId() { + return this.getId().getUri().toString().substring(this.getId().getUri().toString().indexOf("function:")); + } + + /** + * Returns a shortened version of the given DataType Id, primarily for use with error messages to prevent them from becoming too long. + * This is a simple convenience method to reduce code bloat. + * + * @param identifier expected to have '#' in it, and if no '#' should have ":data-type:" + * @return + */ + public String getShortDataTypeId(Identifier identifier) { + String idString = identifier.stringValue(); + int index = idString.indexOf("#"); + if (index < 0) { + index = idString.indexOf(":data-type:"); + if (index < 0) { + return idString; + } else { + return idString.substring(index + 11); + } + } else { + return idString.substring(index+1); + } + } + + /** + * Return a new Status that includes the name of this function in front of the original status' message. + * This is a convenience method to reduce code bloat. + * + * @param originalStatu + * @return + */ + public Status getFunctionStatus(Status originalStatus) { + return new StdStatus(originalStatus.getStatusCode(), getShortFunctionId() + " " + originalStatus.getStatusMessage()); + } + + + // + // Getters for the internal variables + // + + @Override + public Identifier getId() { + return this.id; + } + + @Override + public Identifier getDataTypeId() { + if (this.dataTypeReturn == null) { + return null; + } else { + return this.dataTypeReturn.getId(); + } + } + + public DataType<O> getDataType() { + return this.dataTypeReturn; + } + + /** + * Return the Identifier for the Input Argument(s) DataType. + * + * @return + */ + public DataType<I> getDataTypeArgs() { + return this.dataTypeArgs; + } + + @Override + public boolean returnsBag() { + return returnsBag; + } + + + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java new file mode 100755 index 0000000..a6af460 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionComparison.java @@ -0,0 +1,136 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.util.ArrayList; +import java.util.List; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionComparison implements {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to + * implement the XACML comparison predicates as functions taking two arguments of the same type + * and returning a <code>Boolean</code>. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * integer-greater-than + * integer-greater-than-or-equal + * integer-less-than + * integer-less-than-or-equal + * double-greater-than + * double-greater-than-or-equal + * double-less-than + * double-less-than-or-equal + * + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + * @param <I> the java class for the data type of the function Input arguments + */ +public class FunctionDefinitionComparison<I extends Comparable<I>> extends FunctionDefinitionHomogeneousSimple<Boolean, I> { + + /** + * List of comparison operations. + * + * @author glenngriffin + * + */ + public enum OPERATION {GREATER_THAN, GREATER_THAN_EQUAL, LESS_THAN, LESS_THAN_EQUAL }; + + // the operation for this instance of the class + private OPERATION operation; + + + /** + * Constructor - need dataType input because of java Generic type-erasure during compilation. + * + * @param idIn + * @param dataTypeArgsIn + */ + public FunctionDefinitionComparison(Identifier idIn, DataType<I> dataTypeArgsIn, OPERATION opIn) { + super(idIn, DataTypes.DT_BOOLEAN, dataTypeArgsIn, 2); + operation = opIn; + } + + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + List<I> convertedArguments = new ArrayList<I>(); + Status status = this.validateArguments(arguments, convertedArguments); + + /* + * If the function arguments are not correct, just return an error status immediately + */ + if (!status.getStatusCode().equals(StdStatusCode.STATUS_CODE_OK)) { + return ExpressionResult.newError(getFunctionStatus(status)); + } + + int compareResult; + try { + compareResult = ((I)convertedArguments.get(0)).compareTo((I)convertedArguments.get(1)); + } catch (Exception e) { + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + + switch (operation) { + case GREATER_THAN: + if (compareResult > 0) { + return ER_TRUE; + } else { + return ER_FALSE; + } + + case GREATER_THAN_EQUAL: + if (compareResult > -1) { + return ER_TRUE; + } else { + return ER_FALSE; + } + + case LESS_THAN: + if (compareResult < 0) { + return ER_TRUE; + } else { + return ER_FALSE; + } + + case LESS_THAN_EQUAL: + if (compareResult < 1) { + return ER_TRUE; + } else { + return ER_FALSE; + } + } + + // switch on enum should handle everything - should never get here + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " ENUM did not cover case of " + operation)); + + } + + + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java new file mode 100755 index 0000000..5530065 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionDateTimeArithmetic.java @@ -0,0 +1,125 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + + +import java.util.List; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.DataTypeException; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.IDateTime; +import com.att.research.xacml.std.datatypes.ISO8601Duration; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionDateTimeArithmetic implements {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to + * implement the XACML Date and Time Arithmetic predicates. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * dateTime-add-dayTimeDuration + * dateTime-add-yearMonthDuration + * dateTime-subtract-dayTimeDuration + * dateTime-subtract-yearMonthDuration + * date-add-yearMonthDuration + * date-subtract-yearMonthDuration + * + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + * @param <I> the java class for the data type of the function Input arguments; + * SPECIAL CASE: this applies ONLY to the 2nd argument. + * @param <O> the java class for the data type of the function Output; + * SPECIAL CASE: this ALSO applies to the type of the 1st Input argument. + */ +public class FunctionDefinitionDateTimeArithmetic<O extends IDateTime<O>, I extends ISO8601Duration> extends FunctionDefinitionBase<O, I> { + + /** + * List of Date and Time Arithmetic operations. + * + * @author glenngriffin + * + */ + public enum OPERATION {ADD, SUBTRACT}; + + // operation to be used in this instance of the class + private final OPERATION operation; + + + + /** + * Constructor - need dataTypeArgs input because of java Generic type-erasure during compilation. + * + * @param idIn + * @param dataTypeArgsIn + */ + public FunctionDefinitionDateTimeArithmetic(Identifier idIn, DataType<O> dataTypeIn, DataType<I> dataTypeArgsIn, OPERATION op) { + super(idIn, dataTypeIn, dataTypeArgsIn, false); + this.operation = op; + } + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + if (arguments == null || arguments.size() != 2) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Expected 2 arguments, got " + + ((arguments == null) ? "null" : arguments.size()) )); + } + + // first arg has same type as function output + FunctionArgument functionArgument = arguments.get(0); + ConvertedArgument<O> convertedArgument0 = new ConvertedArgument<O>(functionArgument, this.getDataType(), false); + if ( ! convertedArgument0.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedArgument0.getStatus())); + } + O idateOrig = convertedArgument0.getValue(); + + // second argument is of input type + functionArgument = arguments.get(1); + ConvertedArgument<I> convertedArgument1 = new ConvertedArgument<I>(functionArgument, this.getDataTypeArgs(), false); + if ( ! convertedArgument1.isOk()) { + return ExpressionResult.newError(getFunctionStatus(convertedArgument1.getStatus())); + } + // get the Duration object from the argument which includes all fields, even if the incoming argument does not include them all + ISO8601Duration duration = convertedArgument1.getValue(); + + // add/subtract the duration to the input argument + // + O idateResult = null; + switch(this.operation) { + case ADD: + idateResult = idateOrig.add(duration); + break; + case SUBTRACT: + idateResult = idateOrig.sub(duration); + break; + } + ExpressionResult expressionResult = null; + try { + expressionResult = ExpressionResult.newSingle(this.getDataType().createAttributeValue(idateResult)); + } catch (DataTypeException e) { + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + return expressionResult; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java new file mode 100755 index 0000000..af5c1e6 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionEquality.java @@ -0,0 +1,88 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.util.ArrayList; +import java.util.List; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionEquality extends {@link com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionHomogeneousSimple} to + * implement the XACML Equality predicates as functions taking two arguments of the same data type and returning a <code>Boolean</code>. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * string-equal + * boolean-equal + * integer-equal + * double-equal + * date-equal + * time-equal + * dateTime-equal + * dayTimeDuration-equal + * yearMonthDuration-equal + * anyURI-equal + * + * @author car + * @version $Revision: 1.2 $ + * + * @param <I> the java class for the data type of the function Input arguments + */ +public class FunctionDefinitionEquality<I> extends FunctionDefinitionHomogeneousSimple<Boolean, I> { + + /** + * Determines if the two <code>T</code> values are equal using the java <code>equals</code> method. Derived classes + * may override this if the <code>equals</code> method is not sufficient. + * + * @param v1 the first object to compare + * @param v2 the second object to compare + * @return true if the two objects are the same, else false + */ + protected boolean isEqual(I v1, I v2) { + return v1.equals(v2); + } + + public FunctionDefinitionEquality(Identifier idIn, DataType<I> dataTypeArgsIn) { + super(idIn, DataTypes.DT_BOOLEAN, dataTypeArgsIn, 2); + } + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + List<I> convertedArguments = new ArrayList<I>(); + Status status = this.validateArguments(arguments, convertedArguments); + + /* + * If the function arguments are not correct, just return an error status immediately + */ + if (!status.getStatusCode().equals(StdStatusCode.STATUS_CODE_OK)) { + return ExpressionResult.newError(getFunctionStatus(status)); + } + + /* + * Now just perform the equality operation. + */ + if (this.isEqual(convertedArguments.get(0), convertedArguments.get(1))) { + return ER_TRUE; + } else { + return ER_FALSE; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java new file mode 100755 index 0000000..515cbd5 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHigherOrderBag.java @@ -0,0 +1,523 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.IdentifierImpl; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.Bag; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; +import com.att.research.xacmlatt.pdp.policy.FunctionArgumentAttributeValue; +import com.att.research.xacmlatt.pdp.policy.FunctionDefinition; +import com.att.research.xacmlatt.pdp.std.StdFunctionDefinitionFactory; + +/** + * FunctionDefinitionSet implements {@link com.att.research.xacmlatt.pdp.policy.FunctionDefinition} to + * implement the XACML Set predicates as functions taking two arguments of <code>Bag</code> the same primitive type + * and returning either a <code>Boolean</code> or a <code>Bag</code> of the same primitive type. + * <P> + * The ipAddress, dnsName and xPathExpression do not have set functions defined for them in section 10.2.8 of the Release 3 XACML spec. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * string-bag + * boolean-bag + * integer-bag + * double-bag + * time-bag + * date-bag + * dateTime-bag + * anyURI-bag + * hexBinary-bag + * base64Binary-bag + * dayTimeDuration-bag (version 1 and3) + * yearMonthDuration-bag (version 1 and 3) + * x500Name-bag + * rfc822Name-bag + * + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + * @param <I> the java class for the data type of the function Input arguments + * @param <O> the java class for the data type of the function Output + */ +public class FunctionDefinitionHigherOrderBag<O,I> extends FunctionDefinitionBase<O, I> { + + /** + * List of comparison operations. + * + * @author glenngriffin + * + */ + public enum OPERATION {ANY_OF, ALL_OF, ANY_OF_ANY, ALL_OF_ANY, ANY_OF_ALL, ALL_OF_ALL, MAP }; + + // the operation for this instance of the class + private OPERATION operation; + + + /** + * Constructor - need dataType input because of java Generic type-erasure during compilation. + * + * @param idIn + * @param dataTypeArgsIn + */ + public FunctionDefinitionHigherOrderBag(Identifier idIn, DataType<O> dataTypeIn, DataType<I> dataTypeArgsIn, OPERATION opIn) { + super(idIn, dataTypeIn, dataTypeArgsIn, ((opIn == OPERATION.MAP) ? true : false) ); + operation = opIn; + } + + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + // simple argument check + if (arguments == null || arguments.size() < 2) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Expected at least 2 arguments, got " + + ((arguments == null) ? "null" : arguments.size()) )); + } + + // three functions have some things known about the arguments + if (operation == OPERATION.ALL_OF_ANY || operation == OPERATION.ANY_OF_ALL || operation == OPERATION.ALL_OF_ALL) { + if (arguments.size() != 3) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Expected 3 arguments, got " + arguments.size()) ); + } + // the 2nd & 3rd arguments must both be bags + if ( arguments.get(1) == null || ! arguments.get(1).isBag() ) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " 2nd argument must be bag, got '" + ((arguments.get(1) == null) ? "null" : this.getShortDataTypeId(arguments.get(1).getValue().getDataTypeId())) + "'" )); + } + if (arguments.get(2) == null || ! arguments.get(2).isBag() ) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " 3rd argument must be bag, got '" + ((arguments.get(2) == null) ? "null" : this.getShortDataTypeId(arguments.get(2).getValue().getDataTypeId())) + "'" )); + } + } + + // first argument is supposed to be a Function ID passed to us as an AnyURI + FunctionArgument functionIdArgument = arguments.get(0); + if (functionIdArgument == null || functionIdArgument.getValue() == null) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate Function (first argument) was null")); + } + if ( ! functionIdArgument.getValue().getDataTypeId().equals(DataTypes.DT_ANYURI.getId())) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " First argument expected URI, got " + functionIdArgument.getValue().getDataTypeId() ) ); + } + Identifier functionId = new IdentifierImpl((URI) functionIdArgument.getValue().getValue()); + + // look up the actual function definition based on that ID + StdFunctionDefinitionFactory fdf = new StdFunctionDefinitionFactory(); + + FunctionDefinition predicate = fdf.getFunctionDefinition(functionId); + + if (predicate == null) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " First argument was not URI of a function, got '" + functionId + "'") ); + } + // in all cases except MAP, the predicate must return True/False + if (operation != OPERATION.MAP) { + if ( ! predicate.getDataTypeId().equals(DataTypes.DT_BOOLEAN.getId())) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate Function must return boolean, but '" + predicate.getId() + "' returns '" + this.getShortDataTypeId(predicate.getDataTypeId()) )); + } + } + + + + // The remaining arguments may be either bags or primitive types. + // We do not know what the primitive types will be, and do not concern ourselves about that here + // (the predicate function we just got and will call later will complain if they do not match its expectations). + // The predicate function will want things as FunctionAttributes, so we do not need to unwrap anything. + boolean bagSeen = false; + for (int i = 1; i < arguments.size(); i++) { + FunctionArgument argument = arguments.get(i); + if (argument == null) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Got null argument at index " + i) ); + } + // force evaluation and check status + if ( ! argument.getStatus().isOk()) { + return ExpressionResult.newError(getFunctionStatus(argument.getStatus())); + } + + // for bags, remember that we saw one; for non-bag primitives, check that the primitive value is not null + if (argument.isBag()) { + bagSeen = true; + } else { + if (argument.getValue() == null || argument.getValue().getValue() == null) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Got null attribute at index " + i) ); + } + } + } + + // all functions require at least one bag + if ( ! bagSeen && operation != OPERATION.ANY_OF_ANY) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Did not get any Bag argument; must have at least 1") ); + } + + + // arguments are ready for use + + // list of arguments for passing to the predicate + List<FunctionArgument> predicateArguments = new ArrayList<FunctionArgument>(); + + // for functions that take a single bag, which index is that bag at + int indexOfBagInOriginalArgs = -1; + + // bag iterator + Iterator<AttributeValue<?>> bagIterator1; + Iterator<AttributeValue<?>> bagIterator2; + + + + + switch (operation) { + + case ANY_OF: + // Copy the primitive arguments to the list for passing to the predicate, + // putting a place-holder in for the value from the (single) bag + for (int i = 1; i < arguments.size(); i++) { + predicateArguments.add(arguments.get(i)); + if (arguments.get(i).isBag()) { + if (indexOfBagInOriginalArgs == -1) { + indexOfBagInOriginalArgs = i ; + } else { + // bag already found - we should have only one + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " must have only 1 bag; found one at index " + indexOfBagInOriginalArgs + " and another at " + i) ); + } + } + } + + // get each primitive value in turn + bagIterator1 = arguments.get(indexOfBagInOriginalArgs).getBag().getAttributeValues(); + while (bagIterator1.hasNext()) { + // all of the predicate arguments have been created except that the one from the bag needs to replace the place-holder in the list + predicateArguments.set(indexOfBagInOriginalArgs - 1, new FunctionArgumentAttributeValue(bagIterator1.next())); + ExpressionResult res = predicate.evaluate(evaluationContext, predicateArguments); + if ( ! res.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate error: " + res.getStatus().getStatusMessage()) ); + } + if ( (Boolean)(res.getValue().getValue()) == true) { + return ER_TRUE; + } + } + + return ER_FALSE; + + + + case ALL_OF: + // Copy the primitive arguments to the list for passing to the predicate, + // putting a place-holder in for the value from the (single) bag + for (int i = 1; i < arguments.size(); i++) { + predicateArguments.add(arguments.get(i)); + if (arguments.get(i).isBag()) { + if (indexOfBagInOriginalArgs == -1) { + indexOfBagInOriginalArgs = i ; + } else { + // bag already found - we should have only one + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " must have only 1 bag; found one at index " + indexOfBagInOriginalArgs + " and another at " + i) ); + } + } + } + + // get each primitive value in turn + bagIterator1 = arguments.get(indexOfBagInOriginalArgs).getBag().getAttributeValues(); + while (bagIterator1.hasNext()) { + // all of the predicate arguments have been created except that the one from the bag needs to replace the place-holder in the list + predicateArguments.set(indexOfBagInOriginalArgs - 1, new FunctionArgumentAttributeValue(bagIterator1.next())); + ExpressionResult res = predicate.evaluate(evaluationContext, predicateArguments); + if ( ! res.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate error: " + res.getStatus().getStatusMessage()) ); + } + if ( (Boolean)(res.getValue().getValue()) == false) { + return ER_FALSE; + } + } + return ER_TRUE; + + + case ANY_OF_ANY: + // empty bags can give odd error messages, so check here and return something that makes more sense + for (int i = 1; i < arguments.size(); i++) { + if (arguments.get(i).isBag() && arguments.get(i).getBag().size() == 0) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Bag is empty at index " + i )); + } + } + // This is different from all the other Higher-order bag functions because it can take an unbounded number of arguments any/all of which may be bags. + // (The others take either an unbounded number of args of which exactly 1 is a bag, or they take exactly 2 bags) + // To handle the possibility of multiple bags without knowing a priori how many there might be, + // we first create all possible lists of arguments to be passed to the predicate. + // This is done using a depth-first search of the total argument space. + List<List<FunctionArgument>> listOfPredicateLists = new ArrayList<List<FunctionArgument>>(); + + /* + * Start the recursive append process + */ + appendCrossProduct(new ArrayList<FunctionArgument>(), arguments.subList(1, arguments.size()), 0, listOfPredicateLists); + + // we now have all possible argument lists for the predicate to work on, so do the ANY operation now + for (List<FunctionArgument> predicateArgumentList : listOfPredicateLists) { + // all of the predicate arguments have been created except that the one from the bag needs to replace the place-holder in the list + ExpressionResult res = predicate.evaluate(evaluationContext, predicateArgumentList); + if ( ! res.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate error: " + res.getStatus().getStatusMessage()) ); + } + if ( (Boolean)(res.getValue().getValue()) == true) { + return ER_TRUE; + } + } + + // if we get here then none of the combinations gave a TRUE result + return ER_FALSE; + + + + case ALL_OF_ANY: +//TODO - it might be more efficient to extract all the attributes from the first bag and convert them to FunctionArguments just once, then use that list each time + + // get the element from the 2nd bag that we want to check all elements from the 1st bag against + bagIterator2 = arguments.get(2).getBag().getAttributeValues(); + while (bagIterator2.hasNext()) { + FunctionArgument predicateArgument2 = new FunctionArgumentAttributeValue(bagIterator2.next()); + boolean allMatch = true; + + // now look at every value of the first bag operating with the selected value from the 2nd + bagIterator1 = arguments.get(1).getBag().getAttributeValues(); + while (bagIterator1.hasNext()) { + + predicateArguments.clear(); + predicateArguments.add(new FunctionArgumentAttributeValue(bagIterator1.next())); + predicateArguments.add(predicateArgument2); + + ExpressionResult res = predicate.evaluate(evaluationContext, predicateArguments); + if ( ! res.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate error: " + res.getStatus().getStatusMessage()) ); + } + if ( (Boolean)(res.getValue().getValue()) == false) { + allMatch = false; + break; + } + } + if (allMatch) { + // wee found one value in bag2 that works (is TRUE) for all values in bag1 + return ER_TRUE; + } + // this value from bag2 did not work, so get the next one + } + + // no value in bag2 worked for all values of bag1 + return ER_FALSE; + + + + case ANY_OF_ALL: +//TODO - it might be more efficient to extract all the attributes from the 2nd bag and convert them to FunctionArguments just once, then use that list each time + + // get the element from the 1st bag that we want to check all elements from the 1st bag against + bagIterator1 = arguments.get(1).getBag().getAttributeValues(); + while (bagIterator1.hasNext()) { + FunctionArgument predicateArgument1 = new FunctionArgumentAttributeValue(bagIterator1.next()); + boolean allMatch = true; + + // now look at every value of the 2nd bag operating with the selected value from the first + bagIterator2 = arguments.get(2).getBag().getAttributeValues(); + while (bagIterator2.hasNext()) { + predicateArguments.clear(); + predicateArguments.add(predicateArgument1); + predicateArguments.add(new FunctionArgumentAttributeValue(bagIterator2.next())); + + ExpressionResult res = predicate.evaluate(evaluationContext, predicateArguments); + if ( ! res.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate error: " + res.getStatus().getStatusMessage()) ); + } + if ( (Boolean)(res.getValue().getValue()) == false) { + allMatch = false; + break; + } + } + if (allMatch) { + // wee found one value in bag1 that works (is TRUE) for all values in bag2 + return ER_TRUE; + } + // this value from bag1 did not work, so get the next one + } + + // no value in bag1 worked for all values of bag2 + return ER_FALSE; + + + + case ALL_OF_ALL: +//TODO - it might be more efficient to extract all the attributes from the 2nd bag and convert them to FunctionArguments just once, then use that list each time + + // get the element from the 1st bag that we want to check all elements from the 1st bag against + bagIterator1 = arguments.get(1).getBag().getAttributeValues(); + while (bagIterator1.hasNext()) { + FunctionArgument predicateArgument1 = new FunctionArgumentAttributeValue(bagIterator1.next()); + + // now look at every value of the 2nd bag operating with the selected value from the first + bagIterator2 = arguments.get(2).getBag().getAttributeValues(); + while (bagIterator2.hasNext()) { + predicateArguments.clear(); + predicateArguments.add(predicateArgument1); + predicateArguments.add(new FunctionArgumentAttributeValue(bagIterator2.next())); + + ExpressionResult res = predicate.evaluate(evaluationContext, predicateArguments); + if ( ! res.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate error: " + res.getStatus().getStatusMessage()) ); + } + + if ( (Boolean)(res.getValue().getValue()) == false) { + return ER_FALSE; + } + } + // this value did not fail, so try the next + } + + // everything in bag1 worked (was true) for everything in bag 2 + return ER_TRUE; + + + + case MAP: + // Copy the primitive arguments to the list for passing to the predicate, + // putting a place-holder in for the value from the (single) bag + for (int i = 1; i < arguments.size(); i++) { + predicateArguments.add(arguments.get(i)); + if (arguments.get(i).isBag()) { + if (indexOfBagInOriginalArgs == -1) { + indexOfBagInOriginalArgs = i ; + } else { + // bag already found - we should have only one + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " must have only 1 bag; found one at index " + indexOfBagInOriginalArgs + " and another at " + i) ); + } + } + } + + Bag outputBag = new Bag(); + + // get each primitive value in turn + bagIterator1 = arguments.get(indexOfBagInOriginalArgs).getBag().getAttributeValues(); + while (bagIterator1.hasNext()) { + // all of the predicate arguments have been created except that the one from the bag needs to replace the place-holder in the list + predicateArguments.set(indexOfBagInOriginalArgs - 1, new FunctionArgumentAttributeValue(bagIterator1.next())); + ExpressionResult res = predicate.evaluate(evaluationContext, predicateArguments); + if ( ! res.isOk()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Predicate error: " + res.getStatus().getStatusMessage()) ); + } + if (res.isBag()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Cannot put bag inside bag; predicate was '" + predicate.getId() + "'")); + } + outputBag.add(res.getValue()); + } + + + return ExpressionResult.newBag(outputBag); + + } + + // all cases should have been covered by above - should never get here + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Could not evaluate Higher-Order Bag function " + operation)); + + } + + + + + + + + + + + + + /** + * Performs the depth-first walk to generate argument lists. Needed by any-of-any because of the variable number of bags it might get. + * + * This code was salvaged from the R2 version of the product and adjusted to fit the new way of doing business. + * + * @param argListInProgress the current argument list being generated in this pass + * @param valueList the list of expression result values + * @param nPosition the position within the expression result values to use to append to the base argument list + * @param listArgLists the <code>List</code> where final argument lists are appended + */ + private static void appendCrossProduct(List<FunctionArgument> argListInProgress, List<FunctionArgument> valueList, int nPosition, List<List<FunctionArgument>> listArgLists) { + /* + * Have we hit a leaf? + */ + if (nPosition >= valueList.size()) { + List<FunctionArgument> copy = new ArrayList<FunctionArgument>(); + copy.addAll(argListInProgress); + listArgLists.add(copy); + return; + } + + /* + * Check to see if the value at the current position is a primitive or a bag + */ + FunctionArgument FunctionArgument = valueList.get(nPosition); + if (FunctionArgument.isBag() && FunctionArgument.getBag().getAttributeValues() != null && FunctionArgument.getBag().size() > 0) { + Iterator<AttributeValue<?>> iterBagValues = FunctionArgument.getBag().getAttributeValues(); + while (iterBagValues.hasNext()) { + AttributeValue<?> attributeValue = iterBagValues.next(); + FunctionArgument functionArgument = new FunctionArgumentAttributeValue(attributeValue); + argListInProgress.add(functionArgument); + appendCrossProduct(argListInProgress, valueList, nPosition+1, listArgLists); + argListInProgress.remove(argListInProgress.size()-1); + } + } else { + /* + * This is a simple value, so we can just append to the argListInProgress and continue the recursion + */ + argListInProgress.add(FunctionArgument); + appendCrossProduct(argListInProgress, valueList, nPosition+1, listArgLists); + argListInProgress.remove(argListInProgress.size()-1); + } + } + + + + + + + + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java new file mode 100755 index 0000000..a41ccbe --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionHomogeneousSimple.java @@ -0,0 +1,142 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.util.List; + +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionHomogeneousSimple extends {@link com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionSimple} + * with utility methods for ensuring the types of the arguments passed in the <code>evaluate</code> method matches the parameterized + * type, and the number of arguments is correct. + * When evaluated the resulting arguments must be simple data types, not bags. + * + * The various functions have the following needs with respect to their arguments: + * <UL> + * <LI> + * The argument list size is pre-defined and all arguments can be evaluated at once before the function is called. + * <LI> + * The argument list size is pre-defined but the arguments must be evaluated one at a time by the function. + * <LI> + * The argument list size is not pre-defined. + * </UL> + * To support those needs this class includes methods for checking the list size and evaluating a single argument as well as + * combining those operations in a single method to make it simpler for the calling function. + * + * @author car + * @version $Revision: 1.3 $ + * + * @param <O> the java class for the value of the Output return result from the <code>FunctionDefinition</code> + * @param <I> the java class for the value of the Input {@link com.att.research.xacmlatt.pdp.policy.FunctionArgument}s in the <code>evaluate</code> method + */ +public abstract class FunctionDefinitionHomogeneousSimple<O,I> extends FunctionDefinitionBase<O,I> { + + + // null means that number of arguments is variable + private Integer numArgs; + + /** + * Constructor + * + * @param idIn + * @param dataTypeReturnIn + * @param dataTypeArgsIn + * @param nArgs + */ + public FunctionDefinitionHomogeneousSimple(Identifier idIn, DataType<O> dataTypeReturnIn, DataType<I> dataTypeArgsIn, Integer nArgs) { + super(idIn, dataTypeReturnIn, dataTypeArgsIn, false); + this.numArgs = nArgs; + } + + + /** + * Gets the number of arguments expected to this <code>FunctionDefinition</code>. + * For functions without a pre-defined number of arguments this is not used. + * + * @return the number of arguments expected to this <code>FunctionDefinition</code>. + */ + public Integer getNumArgs() { + return this.numArgs; + } + + + /** + * Validates the given <code>List</code> of <code>FunctionArgument</code>s has the correct count and <code>DataType</code> and evaluates expressions. + * This combines both the argument list length check and the evaluation of all arguments on that list. + * + * @param listFunctionArguments the <code>List</code> of <code>FunctionArgument</code>s to validate + * @return a {@link com.att.research.xacml.api.Status} indication with an error if the arguments are not valid + */ + public Status validateArguments(List<FunctionArgument> listFunctionArguments, List<I> convertedValues) { + /* + * See if we have to validate the number of arguments + */ + Status listLengthStatus = validateArgumentListLength(listFunctionArguments); + if ( ! listLengthStatus.isOk()) { + return listLengthStatus; + } + + + /* + * Now validate the types of the arguments + */ + for (int i = 0; i < listFunctionArguments.size(); i++) { + FunctionArgument functionArgument = listFunctionArguments.get(i); + ConvertedArgument<I> argument = new ConvertedArgument<I>(functionArgument, getDataTypeArgs(), false); + if ( ! argument.isOk()) { + // when a Status is returned that indicates an error, tell caller which arg had problem + Status decoratedStatus = new StdStatus(argument.getStatus().getStatusCode(), argument.getStatus().getStatusMessage() + " at arg index " + i ); + return decoratedStatus; + } + if (convertedValues != null) { + convertedValues.add(argument.getValue()); + } + } + + /* + * Everything passed the data type test, so we are good to go + */ + return StdStatus.STATUS_OK; + } + + + /** + * Validates the given <code>List</code> of <code>FunctionArgument</code>s has the correct count. + * + * @param listFunctionArguments the <code>List</code> of <code>FunctionArgument</code>s to validate + * @return a {@link com.att.research.xacml.api.Status} indication with an error if the arguments are not valid + */ + public Status validateArgumentListLength(List<FunctionArgument> listFunctionArguments) { + /* + * See if we have to validate the number of arguments + */ + if ((listFunctionArguments == null && this.numArgs > 0 ) || + (listFunctionArguments != null && this.numArgs != listFunctionArguments.size()) ) { + return new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, "Expected " + this.numArgs + " arguments, got " + + ((listFunctionArguments == null) ? 0 : listFunctionArguments.size()) ); + } + + /* + * Everything passed the data type test, so we are good to go + */ + return StdStatus.STATUS_OK; + } + + + + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java new file mode 100755 index 0000000..a99456b --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionLogical.java @@ -0,0 +1,219 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.util.List; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionLogical extends {@link com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionHomogeneousSimple} to + * implement the XACML Logic predicates as functions taking zero, one, or multiple arguments of type <code>Boolean</code> and returning a <code>Boolean</code>. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * or + * and + * n-of + * not + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + */ +public class FunctionDefinitionLogical extends FunctionDefinitionHomogeneousSimple<Boolean,Boolean> { + + /** + * List of Logical Operations types + * + * @author glenngriffin + * + */ + public enum OPERATION {OR, AND, N_OF, NOT} + + // the operation that this instance is being asked to do + private final OPERATION operation; + + + public FunctionDefinitionLogical(Identifier idIn, OPERATION op) { + super(idIn, DataTypes.DT_BOOLEAN, DataTypes.DT_BOOLEAN, null); + operation = op; + } + + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + switch (operation) { + case OR: + if (arguments == null || arguments.size() == 0) { + return ER_FALSE; + } + try { + // evaluate the arguments one at a time and abort on the first true + for (int i = 0; i < arguments.size(); i++) { + ConvertedArgument<Boolean> argument = new ConvertedArgument<Boolean>(arguments.get(i), this.getDataTypeArgs(), false); + if ( ! argument.isOk()) { + // return a decorated message + return ExpressionResult.newError(getFunctionStatus(argument.getStatus())); + } + if (argument.getValue() == true) { + return ER_TRUE; + } + } + } catch (Exception e) { + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + return ER_FALSE; + + + case AND: + if (arguments == null || arguments.size() == 0) { + return ER_TRUE; + } + try { + // evaluate the arguments one at a time and abort on the first false + for (int i = 0; i < arguments.size(); i++) { + ConvertedArgument<Boolean> argument = new ConvertedArgument<Boolean>(arguments.get(i), this.getDataTypeArgs(), false); + if ( ! argument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(argument.getStatus())); + } + if (argument.getValue() == false) { + return ER_FALSE; + } + } + + } catch (Exception e) { + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + return ER_TRUE; + + + case N_OF: + Integer argumentCountNeeded; + int trueArgumentsSeen = 0; + if (arguments == null || arguments.size() == 0) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Expected 1 argument, got 0")); + } + try { + // + // Special case: + // The first argument in the list (an Integer) is not homogeneous with the rest of the arguments (Booleans). + // While this is technically not a FunctionDefinitionHomogeneousSimple type of object, we derive from that class anyway + // so that we can take advantage of the validateArgument() method in that class. + // Unfortunately we cannot re-use that same code (because of generics - it gets messy) for the Integer argument. + // The following code essentially does the same job as validateArgument() on the first argument in the list. + // + + // first arg is the number of remaining arguments that must be TRUE + if (arguments.get(0) == null) { + return ER_TRUE; + } + if ( ! arguments.get(0).getStatus().isOk()) { + return ExpressionResult.newError(getFunctionStatus(arguments.get(0).getStatus())); + } + if (arguments.get(0).isBag()) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Expected a simple value, saw a bag")); + } + AttributeValue<?> attributeValue = arguments.get(0).getValue(); + if (attributeValue == null) { + // assume this is the same as "first argument is 0" + return ER_TRUE; + } + + argumentCountNeeded = DataTypes.DT_INTEGER.convert(attributeValue.getValue()).intValue(); + if (argumentCountNeeded == 0) { + return ER_TRUE; + } + if (arguments.size() - 1 < argumentCountNeeded) { + // return a non-OK status to signal indeterminate + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + + " Expected " + argumentCountNeeded + " arguments but only " + + (arguments.size() - 1) + " arguments in list after the count")); + } + for (int i = 1; i < arguments.size(); i++) { + ConvertedArgument<Boolean> argument = new ConvertedArgument<Boolean>(arguments.get(i), this.getDataTypeArgs(), false); + if ( ! argument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(argument.getStatus())); + } + if ((argument.getValue()) == true) { + trueArgumentsSeen++; + if (trueArgumentsSeen >= argumentCountNeeded) { + return ER_TRUE; + } + } + // if we cannot reach the goal, stop now. + // remaining entries to be looked at = list size - i - 1, which is the most additional TRUEs that we could get. + if ( (arguments.size() - i - 1) + trueArgumentsSeen < argumentCountNeeded) { + // do not evaluate remaining entries + return ER_FALSE; + } + } + // did not reach our goal + return ER_FALSE; + + } catch (Exception e) { + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + + + case NOT: + if (arguments == null || arguments.size() != 1) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Expected 1 argument, got " + + ((arguments == null) ? "null" : arguments.size()) ) ); + } + try { + ConvertedArgument<Boolean> argument = new ConvertedArgument<Boolean>(arguments.get(0), this.getDataTypeArgs(), false); + if ( ! argument.isOk()) { + return ExpressionResult.newError(getFunctionStatus(argument.getStatus())); + } + if (argument.getValue() == true) { + return ER_FALSE; + } else { + return ER_TRUE; + } + } catch (Exception e) { + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + } + + // all cases should have been covered by above - should never get here + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " Could not evaluate Logical function " + operation)); + + } + + + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java new file mode 100755 index 0000000..ce5ec07 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionNumberTypeConversion.java @@ -0,0 +1,90 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +import com.att.research.xacml.api.AttributeValue; +import com.att.research.xacml.api.DataType; +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.api.XACML; +import com.att.research.xacml.std.StdAttributeValue; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionNumberTypeConversion extends {@link FunctionDefinitionHomogeneousSimple} to + * implement the XACML predicates foc converting <code>Double</code> to <code>Integer</code> and vice versa. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * double-to-integer + * integer-to-double + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + * @param <O> the java class for the data type of the function Output + * @param <I> the java class for the data type of the function Input argument + */ +public class FunctionDefinitionNumberTypeConversion<O extends Number, I extends Number> extends FunctionDefinitionHomogeneousSimple<O, I> { + + + public FunctionDefinitionNumberTypeConversion(Identifier idIn, DataType<O> outputType, DataType<I> argType) { + super(idIn, outputType, argType, 1); + + } + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + List<I> convertedArguments = new ArrayList<I>(); + Status status = this.validateArguments(arguments, convertedArguments); + + /* + * If the function arguments are not correct, just return an error status immediately + */ + if (!status.getStatusCode().equals(StdStatusCode.STATUS_CODE_OK)) { + return ExpressionResult.newError(getFunctionStatus(status)); + } + + /* + * Numeric operations cannot be operated on generically in java, so we have to check the types and handle separately. + * Whichever type the argument is, convert it to the other + */ + ExpressionResult expressionResult; + try { + if (convertedArguments.get(0).getClass() == BigInteger.class) { + AttributeValue<Double> doubleResult = new StdAttributeValue<Double>(XACML.ID_DATATYPE_DOUBLE, + new Double( ((BigInteger)convertedArguments.get(0)).toString() ) ); + expressionResult = ExpressionResult.newSingle(doubleResult); + } else { + AttributeValue<BigInteger> integerResult = new StdAttributeValue<BigInteger>(XACML.ID_DATATYPE_INTEGER, BigInteger.valueOf(((Double)convertedArguments.get(0)).intValue()) ); + expressionResult = ExpressionResult.newSingle(integerResult); + } + } catch (Exception e) { + String message = e.getMessage(); + if (e.getCause() != null) { + message = e.getCause().getMessage(); + } + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, this.getShortFunctionId() + " " + message)); + } + + return expressionResult; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/94fcdd90/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java ---------------------------------------------------------------------- diff --git a/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java new file mode 100755 index 0000000..5015204 --- /dev/null +++ b/openaz-xacml-pdp/src/main/java/com/att/research/xacmlatt/pdp/std/functions/FunctionDefinitionRFC822NameMatch.java @@ -0,0 +1,141 @@ +/* + * AT&T - PROPRIETARY + * THIS FILE CONTAINS PROPRIETARY INFORMATION OF + * AT&T AND IS NOT TO BE DISCLOSED OR USED EXCEPT IN + * ACCORDANCE WITH APPLICABLE AGREEMENTS. + * + * Copyright (c) 2013 AT&T Knowledge Ventures + * Unpublished and Not for Publication + * All Rights Reserved + */ +package com.att.research.xacmlatt.pdp.std.functions; + +import java.util.List; + +import com.att.research.xacml.api.Identifier; +import com.att.research.xacml.api.Status; +import com.att.research.xacml.std.StdStatus; +import com.att.research.xacml.std.StdStatusCode; +import com.att.research.xacml.std.datatypes.DataTypes; +import com.att.research.xacml.std.datatypes.RFC822Name; +import com.att.research.xacmlatt.pdp.eval.EvaluationContext; +import com.att.research.xacmlatt.pdp.policy.ExpressionResult; +import com.att.research.xacmlatt.pdp.policy.FunctionArgument; + +/** + * FunctionDefinitionRFC822NameMatch extends {@link com.att.research.xacmlatt.pdp.std.functions.FunctionDefinitionHomogeneousSimple} to + * implement the XACML RFC822Name match predicate as functions taking one <code>String</code> and one <code>RFC822Name</code> arguments + * and returning a single <code>Boolean</code> value. + * + * In the first implementation of XACML we had separate files for each XACML Function. + * This release combines multiple Functions in fewer files to minimize code duplication. + * This file supports the following XACML codes: + * rfc822Name-match + * + * @author glenngriffin + * @version $Revision: 1.1 $ + * + */ +public class FunctionDefinitionRFC822NameMatch extends FunctionDefinitionBase<Boolean, RFC822Name> { + + + /** + * Constructor + * + * @param idIn + * @param dataTypeArgsIn + * @param op + */ + public FunctionDefinitionRFC822NameMatch(Identifier idIn) { + super(idIn, DataTypes.DT_BOOLEAN, DataTypes.DT_RFC822NAME, false); + } + + + @Override + public ExpressionResult evaluate(EvaluationContext evaluationContext, List<FunctionArgument> arguments) { + + if (arguments == null || arguments.size() != 2) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + " Expected 2 arguments, got " + + ((arguments == null) ? "null" : arguments.size()) )); + } + + // get the string to search for + ConvertedArgument<String> stringArgument = new ConvertedArgument<String>(arguments.get(0), DataTypes.DT_STRING, false); + if ( ! stringArgument.isOk()) { + Status decoratedStatus = new StdStatus(stringArgument.getStatus().getStatusCode(), stringArgument.getStatus().getStatusMessage() + " at arg index 0" ); + return ExpressionResult.newError(getFunctionStatus(decoratedStatus)); + } + String searchTermString = stringArgument.getValue(); + + // get the RFC822Name to match with + ConvertedArgument<RFC822Name> rfc822Argument = new ConvertedArgument<RFC822Name>(arguments.get(1), DataTypes.DT_RFC822NAME, false); + if ( ! rfc822Argument.isOk()) { + Status decoratedStatus = new StdStatus(rfc822Argument.getStatus().getStatusCode(), rfc822Argument.getStatus().getStatusMessage() + " at arg index 1" ); + return ExpressionResult.newError(getFunctionStatus(decoratedStatus)); + } + + RFC822Name rfc822Name = rfc822Argument.getValue(); + + + /* + * Now perform the match. + */ + + /* + * According to the spec the string must be one of the following 3 things: + * - a name with an '@' in it = a full name that must exactly match the whole RFC name (domain part is ignore case) + * - a domain name (without an '@' and not starting with a '.') = must match whole RFC domain name (ignore case) + * - a partial domain name (without an '@') starting with a '.' = the last part of the RFC domain name (ignore case) + */ + + String[] searchTerms = searchTermString.split("@"); + + if (searchTerms.length > 2) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + + " String contained more than 1 '@' in '" + searchTermString + "'" )); + } + + if (searchTerms.length == 2 || searchTermString.endsWith("@")) { + // this is an exact match + if (searchTerms[0] == null || searchTerms[0].length() == 0) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + + " String missing local part in '" + searchTermString + "'" )); + } + if (searchTerms.length < 2 || searchTerms[1] == null || searchTerms[1].length() == 0) { + return ExpressionResult.newError(new StdStatus(StdStatusCode.STATUS_CODE_PROCESSING_ERROR, getShortFunctionId() + + " String missing domain part in '" + searchTermString + "'" )); + } + + // args are ok, so check both against RFC name + if (searchTerms[0].equals(rfc822Name.getLocalName()) && + searchTerms[1].toLowerCase().equals(rfc822Name.getCanonicalDomainName())) { + return ER_TRUE; + } else { + return ER_FALSE; + } + } + + // we have only a domain name, which may be whole or partial + + // make it match the canonical version + searchTerms[0] = searchTerms[0].toLowerCase(); + + if (searchTerms[0].charAt(0) == '.') { + // name is partial - must match the end + if (rfc822Name.getCanonicalDomainName().endsWith(searchTerms[0])) { + return ER_TRUE; + } else { + return ER_FALSE; + } + } else { + // name is whole domain - must match exactly + if (rfc822Name.getCanonicalDomainName().equals(searchTerms[0])) { + return ER_TRUE; + } else { + return ER_FALSE; + } + } + + } + +}
