Commit 4c0951ed authored by cdanger's avatar cdanger

Merge branch 'release/11.0.1'

parents 2e8fa998 5e0e5594
......@@ -7,3 +7,4 @@
/.pmdruleset.xml
/.project
/.checkstyle
/bin/
language: java
jdk:
- openjdk8
# Change log
All notable changes to this project are documented in this file following the [Keep a CHANGELOG](http://keepachangelog.com) conventions.
Issues reported on [GitHub](https://github.com/authzforce/core/issues) are referenced in the form of `[GH-N]`, where N is the issue number. Issues reported on [OW2](https://jira.ow2.org/browse/AUTHZFORCE/) are mentioned in the form of `[OW2-N]`, where N is the issue number.
## Issue references
- Issues reported on [GitHub](https://github.com/authzforce/core/issues) are referenced in the form of `[GH-N]`, where N is the issue number.
- Issues reported on [OW2's JIRA](https://jira.ow2.org/browse/AUTHZFORCE/) are referenced in the form of `[JIRA-N]`, where N is the issue number.
- Issues reported on [OW2's GitLab](https://gitlab.ow2.org/authzforce/core/issues) are referenced in the form of `[GL-N]`, where N is the issue number.
## 11.0.1
### Fixed
- [GL-6]: IllegalArgumentException when applying XACML 'map' function to substring with string bag as first arg
- Dependency of pdp-testutils module - Jongo 1.3.0 - depends on jackson-databind 2.7.3 which is affected by CVE-2018-5968. Fixed by forcing version of jackson-databind to 2.9.4 in file 'pom.xml', until Jongo team fixes the issue (https://github.com/bguerout/jongo/issues/327)
## 11.0.0
......@@ -118,10 +127,10 @@ XACML 3.0, and adapting to the PDP engine API; also provides automatic conversio
## 7.1.0
### Added
- [OW2-26] Simplify evaluation of Apply expression with commutative numeric function f (e.g. add and multiply): if multiple arguments are constants A, B..., then: `f(a1,...an, A, b1,...bn, B, c1,...) = f(C, a1,...an, b1,...bn, c1...)` where `C = f(A,B...)` and a1,...an, b1,...bn, c1,... are the other arguments (variables).
- [JIRA-26] Simplify evaluation of Apply expression with commutative numeric function f (e.g. add and multiply): if multiple arguments are constants A, B..., then: `f(a1,...an, A, b1,...bn, B, c1,...) = f(C, a1,...an, b1,...bn, c1...)` where `C = f(A,B...)` and a1,...an, b1,...bn, c1,... are the other arguments (variables).
### Fixed
- [OW2-25] - Reopened - NullPointerException when parsing Apply expressions using invalid/unsupported Function ID. This is the final fix addressing higher-order functions. (Initial fix only addressed first-order ones.)
- [JIRA-25] - Reopened - NullPointerException when parsing Apply expressions using invalid/unsupported Function ID. This is the final fix addressing higher-order functions. (Initial fix only addressed first-order ones.)
- Artifact `authzforce-ce-core` with `tests` classifier: missing classes.
......@@ -174,10 +183,10 @@ XACML 3.0, and adapting to the PDP engine API; also provides automatic conversio
- Dependency on Koloboke, replaced by extension mechanism mentioned in *Added* section that would allow to switch from the default HashMap/HashSet implementation to Koloboke-based.
### Fixed
- [OW2-23] Enforcement of RuleId/PolicyId/PolicySetId uniqueness:
- [JIRA-23] Enforcement of RuleId/PolicyId/PolicySetId uniqueness:
- PolicyId (resp. PolicySetId) should be unique across all policies loaded by PDP so that PolicyIdReferences (resp. PolicySetIdReferences) in Responses' PolicyIdentifierList are absolute references to applicable policies (no ambiguity).
- [RuleId should be unique within a policy](https://lists.oasis-open.org/archives/xacml/201310/msg00025.html) -> A rule is globally uniquely identified by the parent PolicyId and the RuleId.
- [OW2-25] NullPointerException when parsing Apply expressions using invalid/unsupported Function ID. Partial fix addressing only invalid first-order functions. See release 7.0.1 for final fix addressing higher-order functions too.
- [JIRA-25] NullPointerException when parsing Apply expressions using invalid/unsupported Function ID. Partial fix addressing only invalid first-order functions. See release 7.0.1 for final fix addressing higher-order functions too.
## 5.0.2
......@@ -187,7 +196,7 @@ XACML 3.0, and adapting to the PDP engine API; also provides automatic conversio
## 5.0.1
### Fixed
- [OW2-22] When handling the same XACML Request twice in the same JVM with the root PolicySet using deny-unless-permit algorithm over a Policy returning simple Deny (no status/obligation/advice) and a Policy returning Permit/Deny with obligations/advice, the obligation is duplicated in the final result at the second time this situation occurs.
- [JIRA-22] When handling the same XACML Request twice in the same JVM with the root PolicySet using deny-unless-permit algorithm over a Policy returning simple Deny (no status/obligation/advice) and a Policy returning Permit/Deny with obligations/advice, the obligation is duplicated in the final result at the second time this situation occurs.
- XACML StatusCode XML serialization/marshalling error when Missing Attribute info that is no valid anyURI is returned by PDP in a Indeterminate Result
- Memory management issue: native RootPolicyProvider modules keeping a reference to static refPolicyProvider, even after policies have been resolved statically at initialization time, preventing garbage collection and memory saving.
- Calls to Logger impacted negatively by autoboxing
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>11.0.0</version>
<version>11.0.1</version>
<relativePath>..</relativePath>
</parent>
<artifactId>authzforce-ce-core-pdp-cli</artifactId>
......@@ -30,12 +30,12 @@
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-engine</artifactId>
<version>11.0.0</version>
<version>11.0.1</version>
</dependency>
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-io-xacml-json</artifactId>
<version>11.0.0</version>
<version>11.0.1</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
......@@ -46,7 +46,7 @@
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-testutils</artifactId>
<version>11.0.0</version>
<version>11.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
......
This diff is collapsed.
......@@ -177,14 +177,14 @@ public final class BasePdpEngine implements CloseablePdpEngine
}
@Override
public Bag<?> putNamedAttributeIfAbsent(final AttributeFqn AttributeFqn, final AttributeBag<?> attributeValues)
public Bag<?> putNamedAttributeIfAbsent(final AttributeFqn attributeFqn, final AttributeBag<?> attributeValues)
{
/*
* Put the non-issued version of the attribute first
*/
final AttributeFqn nonAttributeFqn = AttributeFqns.newInstance(AttributeFqn.getCategory(), Optional.empty(), AttributeFqn.getId());
final AttributeFqn nonAttributeFqn = AttributeFqns.newInstance(attributeFqn.getCategory(), Optional.empty(), attributeFqn.getId());
super.putNamedAttributeIfAbsent(nonAttributeFqn, attributeValues);
return super.putNamedAttributeIfAbsent(AttributeFqn, attributeValues);
return super.putNamedAttributeIfAbsent(attributeFqn, attributeValues);
}
}
......@@ -255,9 +255,9 @@ public final class BasePdpEngine implements CloseablePdpEngine
/** {@inheritDoc} */
@Override
public <AV extends AttributeValue> AttributeBag<AV> getNamedAttributeValue(final AttributeFqn AttributeFqn, final BagDatatype<AV> attributeBagDatatype) throws IndeterminateEvaluationException
public <AV extends AttributeValue> AttributeBag<AV> getNamedAttributeValue(final AttributeFqn attributeFqn, final BagDatatype<AV> attributeBagDatatype) throws IndeterminateEvaluationException
{
final AttributeBag<?> bagResult = namedAttributes.get(AttributeFqn);
final AttributeBag<?> bagResult = namedAttributes.get(attributeFqn);
if (bagResult == null)
{
return null;
......@@ -270,7 +270,7 @@ public final class BasePdpEngine implements CloseablePdpEngine
"Datatype ("
+ bagResult.getElementDatatype()
+ ") of AttributeDesignator "
+ AttributeFqn
+ attributeFqn
+ " in context is different from expected/requested ("
+ expectedElementDatatype
+ "). May be caused by refering to the same Attribute Category/Id/Issuer with different Datatypes in different policy elements and/or attribute providers, which is not allowed.",
......@@ -281,14 +281,14 @@ public final class BasePdpEngine implements CloseablePdpEngine
* If datatype classes match, bagResult should have same type as datatypeClass.
*/
final AttributeBag<AV> result = (AttributeBag<AV>) bagResult;
this.listeners.forEach((lt, l) -> l.namedAttributeValueConsumed(AttributeFqn, result));
this.listeners.forEach((lt, l) -> l.namedAttributeValueConsumed(attributeFqn, result));
return result;
}
@Override
public boolean putNamedAttributeValueIfAbsent(final AttributeFqn AttributeFqn, final AttributeBag<?> result)
public boolean putNamedAttributeValueIfAbsent(final AttributeFqn attributeFqn, final AttributeBag<?> result)
{
final Bag<?> duplicate = namedAttributes.putIfAbsent(AttributeFqn, result);
final Bag<?> duplicate = namedAttributes.putIfAbsent(attributeFqn, result);
if (duplicate != null)
{
/*
......@@ -296,11 +296,11 @@ public final class BasePdpEngine implements CloseablePdpEngine
* putAttributeDesignatorResultIfAbsent() in this case. In any case, we do not support setting a different result for same id (but different datatype URI/datatype class) in the same
* context
*/
LOGGER.warn("Attempt to override value of AttributeDesignator {} already set in evaluation context. Overriding value: {}", AttributeFqn, result);
LOGGER.warn("Attempt to override value of AttributeDesignator {} already set in evaluation context. Overriding value: {}", attributeFqn, result);
return false;
}
this.listeners.forEach((lt, l) -> l.namedAttributeValueProduced(AttributeFqn, result));
this.listeners.forEach((lt, l) -> l.namedAttributeValueProduced(attributeFqn, result));
/*
* Attribute value cannot change during evaluation context, so if old value already there, put it back
*/
......
......@@ -51,11 +51,11 @@ public enum StandardEnvironmentAttribute
*/
CURRENT_DATETIME(AttributeFqns.newInstance(XacmlAttributeCategory.XACML_3_0_ENVIRONMENT.value(), Optional.empty(), XacmlAttributeId.XACML_1_0_ENVIRONMENT_CURRENT_DATETIME.value()));
private final AttributeFqn AttributeFqn;
private final AttributeFqn attributeFqn;
private StandardEnvironmentAttribute(final AttributeFqn AttributeFqn)
private StandardEnvironmentAttribute(final AttributeFqn attributeFqn)
{
this.AttributeFqn = AttributeFqn;
this.attributeFqn = attributeFqn;
}
/**
......@@ -65,7 +65,7 @@ public enum StandardEnvironmentAttribute
*/
public AttributeFqn getFQN()
{
return this.AttributeFqn;
return this.attributeFqn;
}
private static final Map<AttributeFqn, StandardEnvironmentAttribute> ID_TO_STD_ATTR_MAP = Maps.uniqueIndex(Arrays.asList(StandardEnvironmentAttribute.values()),
......@@ -84,12 +84,12 @@ public enum StandardEnvironmentAttribute
/**
* Get the standard environment attribute corresponding to the given ID
*
* @param AttributeFqn
* @param attributeFqn
* standard attribute ID
* @return StandardEnvironmentAttribute corresponding to given ID, or null if there is no standard environment attribute with such ID
*/
public static StandardEnvironmentAttribute getInstance(final AttributeFqn AttributeFqn)
public static StandardEnvironmentAttribute getInstance(final AttributeFqn attributeFqn)
{
return ID_TO_STD_ATTR_MAP.get(AttributeFqn);
return ID_TO_STD_ATTR_MAP.get(attributeFqn);
}
}
......@@ -22,7 +22,9 @@ import java.util.Set;
import org.ow2.authzforce.core.pdp.api.Decidable;
import org.ow2.authzforce.core.pdp.api.combining.CombiningAlg;
import org.ow2.authzforce.core.pdp.api.combining.CombiningAlgRegistry;
import org.ow2.authzforce.core.pdp.api.policy.PolicyEvaluator;
import org.ow2.authzforce.core.pdp.impl.BasePdpExtensionRegistry;
import org.ow2.authzforce.core.pdp.impl.rule.RuleEvaluator;
import com.google.common.base.Preconditions;
......@@ -31,8 +33,7 @@ import com.google.common.base.Preconditions;
*
* @version $Id: $
*/
public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistry<CombiningAlg<?>>
implements CombiningAlgRegistry
public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistry<CombiningAlg<?>> implements CombiningAlgRegistry
{
/**
* <p>
......@@ -44,15 +45,16 @@ public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistr
*/
public ImmutableCombiningAlgRegistry(Set<CombiningAlg<?>> algorithms)
{
super(CombiningAlg.class,
Preconditions.checkNotNull(algorithms, "Input Combining Algorithms undefined (algorithms == null)"));
super(CombiningAlg.class, Preconditions.checkNotNull(algorithms, "Input Combining Algorithms undefined (algorithms == null)"));
}
private static String toString(Class<? extends Decidable> combinedElementType) {
return combinedElementType == PolicyEvaluator.class ? "Policy(Set)" : combinedElementType == RuleEvaluator.class ? "Rule" : combinedElementType.getCanonicalName();
}
/** {@inheritDoc} */
@Override
public <T extends Decidable> CombiningAlg<T> getAlgorithm(String algId, Class<T> combinedEltType)
throws IllegalArgumentException
{
public <T extends Decidable> CombiningAlg<T> getAlgorithm(String algId, Class<T> combinedEltType) throws IllegalArgumentException {
final CombiningAlg<? extends Decidable> alg = this.getExtension(algId);
if (alg == null)
{
......@@ -65,10 +67,9 @@ public final class ImmutableCombiningAlgRegistry extends BasePdpExtensionRegistr
}
// wrong type of alg
throw new IllegalArgumentException("Registered combining algorithm for ID=" + algId
+ " combines instances of type '" + alg.getCombinedElementType()
+ "' which is not compatible (not same or supertype) with requested type of combined elements : "
+ combinedEltType);
alg.getCombinedElementType();
throw new IllegalArgumentException(
"Combining algorithm '" + algId + "': invalid type of input elements (to be combined): " + toString(combinedEltType) + "; expected: " + toString(alg.getCombinedElementType()) + ".");
}
}
......@@ -54,8 +54,7 @@ import org.ow2.authzforce.xacml.identifiers.XacmlStatusCode;
*/
final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<BooleanValue>
{
private static String getInvalidArg0MessagePrefix(final FirstOrderFunctionSignature<?> funcsig)
{
private static String getInvalidArg0MessagePrefix(final FirstOrderFunctionSignature<?> funcsig) {
return "Function " + funcsig.getName() + ": Invalid arg #0 (number of required Trues): expected: 0 <= (integer) <= number_of_remaining_arguments; actual: ";
}
......@@ -81,8 +80,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
}
protected BooleanValue evaluate(final EvaluationContext context, final int requiredMinOfTrues, final Iterator<? extends Expression<?>> remainingArgExpsIterator,
final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException
{
final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException {
assert requiredMinOfTrues <= this.numOfArgsAfterFirst;
int nOfRequiredTrues = requiredMinOfTrues;
......@@ -111,8 +109,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
return BooleanValue.TRUE;
}
}
}
catch (final IndeterminateEvaluationException e)
} catch (final IndeterminateEvaluationException e)
{
/*
* Keep the indeterminate arg error to throw it later in exception, in case there was not enough TRUEs in the remaining args.
......@@ -174,8 +171,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
try
{
attrVal = BooleanValue.class.cast(arg);
}
catch (final ClassCastException e)
} catch (final ClassCastException e)
{
/*
* Indicate arg index to help troubleshooting: argIndex (starting at 0) = max_index - number_of_args_remaining_to_evaluate = (totalArgCount - 1) - nOfRemainingArgs =
......@@ -253,8 +249,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
}
@Override
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... remainingArgs) throws IndeterminateEvaluationException
{
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... remainingArgs) throws IndeterminateEvaluationException {
return super.evaluate(context, requiredMinOfTrues, checkedArgExpressionsAfterFirst.iterator(), remainingArgs);
}
......@@ -274,8 +269,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
}
@Override
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException
{
public BooleanValue evaluate(final EvaluationContext context, final AttributeValue... checkedRemainingArgs) throws IndeterminateEvaluationException {
/*
* Arg datatypes and number is already checked in superclass but we need to do further checks specific to this function such as the first argument which must be a positive integer
*/
......@@ -290,8 +284,7 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
try
{
intAttrVal = Expressions.eval(input0, context, StandardDatatypes.INTEGER);
}
catch (final IndeterminateEvaluationException e)
} catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException(indeterminateArgMsgPrefix + 0, e.getStatusCode(), e);
}
......@@ -334,13 +327,19 @@ final class LogicalNOfFunction extends MultiParameterTypedFirstOrderFunction<Boo
/** {@inheritDoc} */
@Override
public FirstOrderFunctionCall<BooleanValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException
{
public FirstOrderFunctionCall<BooleanValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException {
/*
* Optimization: check whether the first arg ('n' = number of Trues to reach) is constant
*/
final Iterator<? extends Expression<?>> argExpsIterator = argExpressions.iterator();
// Evaluate the first argument
/*
* Evaluate the first argument if not in remainingArgTypes
*/
if (!argExpsIterator.hasNext())
{
return new CallWithVarArg0(functionSignature, argExpressions, remainingArgTypes);
}
final Optional<? extends Value> arg0 = argExpsIterator.next().getValue();
if (arg0.isPresent())
{
......
......@@ -24,6 +24,7 @@ import java.util.List;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.expression.Expression;
import org.ow2.authzforce.core.pdp.api.expression.Expressions;
import org.ow2.authzforce.core.pdp.api.func.FirstOrderFunction;
import org.ow2.authzforce.core.pdp.api.func.GenericHigherOrderFunctionFactory;
import org.ow2.authzforce.core.pdp.api.func.HigherOrderBagFunction;
......@@ -62,28 +63,57 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
private final Datatype<SUB_RETURN> returnBagElementType;
private final String indeterminateSubFuncEvalMessagePrefix;
private Call(final String functionId, final Datatype<Bag<SUB_RETURN>> returnType, final FirstOrderFunction<SUB_RETURN> subFunction, final List<Expression<?>> primitiveInputs,
final Expression<? extends Bag<?>> lastInputBag)
private Call(final String functionId, final Datatype<Bag<SUB_RETURN>> returnType, final FirstOrderFunction<SUB_RETURN> subFunction, final List<Expression<?>> primitiveInputsBeforeBag,
final Expression<? extends Bag<?>> bagInput, List<Expression<?>> primitiveInputsAfterBag)
{
super(functionId, returnType, subFunction, primitiveInputs, lastInputBag);
super(functionId, returnType, subFunction, primitiveInputsBeforeBag, bagInput, primitiveInputsAfterBag);
this.returnBagElementType = subFunction.getReturnType();
this.indeterminateSubFuncEvalMessagePrefix = "Function " + functionId + ": Error calling sub-function (first argument) with last arg=";
this.indeterminateSubFuncEvalMessagePrefix = "Function '" + functionId + "': Error calling sub-function (first argument) with bag arg (#" + this.bagArgIndex + ") = ";
}
@Override
protected Bag<SUB_RETURN> evaluate(final Bag<?> lastArgBag, final EvaluationContext context) throws IndeterminateEvaluationException
{
final Collection<SUB_RETURN> results = new ArrayDeque<>(lastArgBag.size());
for (final AttributeValue lastArgBagVal : lastArgBag)
protected Bag<SUB_RETURN> evaluate(final Bag<?> bagArg, final EvaluationContext context) throws IndeterminateEvaluationException {
/*
* Prepare sub-function call's remaining args (bag arg and subsequent ones if any)
*/
final AttributeValue[] argsAfterBagInclusive = new AttributeValue[this.numOfArgsAfterBagInclusive];
/*
* Index i=0 is for the bag element value, resolved in the second for loop below.
*/
int i = 1;
/*
* See BaseFirstOrderFunctionCall#evalPrimitiveArgs(...)
*/
for (final Expression<?> primitiveArgExprAfterBag : this.primitiveArgExprsAfterBag)
{
final SUB_RETURN subResult;
// get and evaluate the next parameter
/*
* The types of arguments have already been checked with checkInputs(), so casting to returnType should work.
*/
final AttributeValue argVal;
try
{
subResult = subFuncCall.evaluate(context, lastArgBagVal);
argVal = Expressions.evalPrimitive(primitiveArgExprAfterBag, context);
} catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException("Indeterminate arg #" + (this.bagArgIndex + i), e.getStatusCode(), e);
}
catch (final IndeterminateEvaluationException e)
argsAfterBagInclusive[i] = argVal;
i++;
}
final Collection<SUB_RETURN> results = new ArrayDeque<>(bagArg.size());
for (final AttributeValue bagElement : bagArg)
{
argsAfterBagInclusive[0] = bagElement;
final SUB_RETURN subResult;
try
{
subResult = subFuncCall.evaluate(context, argsAfterBagInclusive);
} catch (final IndeterminateEvaluationException e)
{
throw new IndeterminateEvaluationException(indeterminateSubFuncEvalMessagePrefix + lastArgBagVal, e.getStatusCode(), e);
throw new IndeterminateEvaluationException(indeterminateSubFuncEvalMessagePrefix + bagElement, e.getStatusCode(), e);
}
results.add(subResult);
......@@ -105,10 +135,9 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
}
@Override
protected OneBagOnlyHigherOrderFunction.Call<Bag<SUB_RETURN_T>, SUB_RETURN_T> newFunctionCall(final FirstOrderFunction<SUB_RETURN_T> subFunc, final List<Expression<?>> primitiveInputs,
final Expression<? extends Bag<?>> lastInputBag)
{
return new Call<>(this.getId(), this.getReturnType(), subFunc, primitiveInputs, lastInputBag);
protected OneBagOnlyHigherOrderFunction.Call<Bag<SUB_RETURN_T>, SUB_RETURN_T> newFunctionCall(final FirstOrderFunction<SUB_RETURN_T> subFunc,
final List<Expression<?>> primitiveInputsBeforeBag, final Expression<? extends Bag<?>> bagInput, final List<Expression<?>> primitiveInputsAfterBag) {
return new Call<>(this.getId(), this.getReturnType(), subFunc, primitiveInputsBeforeBag, bagInput, primitiveInputsAfterBag);
}
}
......@@ -121,14 +150,12 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
}
@Override
public String getId()
{
public String getId() {
return functionId;
}
@Override
public <SUB_RETURN extends AttributeValue> HigherOrderBagFunction<?, SUB_RETURN> getInstance(final Datatype<SUB_RETURN> subFunctionReturnType) throws IllegalArgumentException
{
public <SUB_RETURN extends AttributeValue> HigherOrderBagFunction<?, SUB_RETURN> getInstance(final Datatype<SUB_RETURN> subFunctionReturnType) throws IllegalArgumentException {
if (subFunctionReturnType == null)
{
throw NULL_SUB_FUNCTION_RETURN_TYPE_ARG_EXCEPTION;
......@@ -136,8 +163,8 @@ final class MapFunctionFactory extends GenericHigherOrderFunctionFactory
if (!(subFunctionReturnType instanceof AttributeDatatype<?>))
{
throw new IllegalArgumentException("Invalid sub-function's return type specified for function '" + functionId + "': " + subFunctionReturnType
+ ". Expected: any primitive attribute datatype.");
throw new IllegalArgumentException(
"Invalid sub-function's return type specified for function '" + functionId + "': " + subFunctionReturnType + ". Expected: any primitive attribute datatype.");
}
return new MapFunction<>(functionId, (AttributeDatatype<SUB_RETURN>) subFunctionReturnType);
......
......@@ -52,8 +52,7 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
private static final IllegalArgumentException UNDEF_PARAMETER_TYPES_EXCEPTION = new IllegalArgumentException("Undefined function parameter types");
private static <AV extends Value> List<Datatype<AV>> validate(final List<Datatype<AV>> paramTypes)
{
private static <AV extends Value> List<Datatype<AV>> validate(final List<Datatype<AV>> paramTypes) {
if (paramTypes == null || paramTypes.isEmpty())
{
throw UNDEF_PARAMETER_TYPES_EXCEPTION;
......@@ -93,13 +92,11 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
}
@Override
protected V evaluate(final Deque<V> args) throws IndeterminateEvaluationException
{
protected V evaluate(final Deque<V> args) throws IndeterminateEvaluationException {
try
{
return op.eval(args);
}
catch (IllegalArgumentException | ArithmeticException e)
} catch (IllegalArgumentException | ArithmeticException e)
{
throw new IndeterminateEvaluationException(invalidArgsErrMsg, XacmlStatusCode.PROCESSING_ERROR.value(), e);
}
......@@ -128,12 +125,11 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
/** {@inheritDoc} */
@Override
public FirstOrderFunctionCall<AV> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException
{
public FirstOrderFunctionCall<AV> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) throws IllegalArgumentException {
/**
* If this.op is a commutative function (e.g. add or multiply function), we can simplify arguments if there are multiple constants. Indeed, if C1,...Cm are constants, then:
* <p>
* op(x1,..., x_{n1-1}, C1, x_n1, ..., x_{n2-1} C2, x_n2, ..., Cm, x_nm...) = op( C, x1.., x_{n1-1}, x_n1, x_{n2-2}, x_n2...), where C (constant) = op(C1, C2..., Cm)
* op(x1,..., x_{n1-1}, C1, x_n1, ..., x_{n2-1}, C2, x_n2, ..., Cm, x_nm...) = op( C, x1.., x_{n1-1}, x_n1, x_{n2-2}, x_n2...), where C (constant) = op(C1, C2..., Cm)
* </p>
* In this case, we can pre-compute constant C and replace all constant args with one: C
*
......@@ -159,18 +155,16 @@ final class NumericArithmeticFunction<AV extends NumericValue<?, AV>> extends Si
{
// variable
finalArgExpressions.add(argExp);
}
else
} else
{
// constant
try
{
constants.add(paramType.cast(v.get()));
}
catch (final ClassCastException e)
} catch (final ClassCastException e)
{
throw new IllegalArgumentException("Function " + this.functionSignature + ": invalid arg #" + argIndex + ": bad type: " + argExp.getReturnType() + ". Expected type: "
+ paramType, e);
throw new IllegalArgumentException(
"Function " + this.functionSignature + ": invalid arg #" + argIndex + ": bad type: " + argExp.getReturnType() + ". Expected type: " + paramType, e);
}
}
......
......@@ -71,8 +71,7 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
}
@Override
protected StringValue evaluate(final Deque<AttributeValue> args) throws IndeterminateEvaluationException
{
protected StringValue evaluate(final Deque<AttributeValue> args) throws IndeterminateEvaluationException {
final AttributeValue rawArg0 = args.poll();
final AttributeValue rawArg1 = args.poll();
final AttributeValue rawArg2 = args.poll();
......@@ -85,8 +84,7 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
arg0 = param0Type.cast(rawArg0);
beginIndex = (IntegerValue) rawArg1;
endIndex = (IntegerValue) rawArg2;
}
catch (final ClassCastException e)
} catch (final ClassCastException e)
{
throw new IndeterminateEvaluationException(invalidArgTypesErrorMsg + rawArg0.getDataType() + "," + rawArg1.getDataType() + "," + rawArg2.getDataType(),
XacmlStatusCode.PROCESSING_ERROR.value(), e);
......@@ -115,8 +113,7 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
final int beginIndexInt = beginIndex.intValueExact();
final int endIndexInt = endIndex.intValueExact();
substring = endIndexInt == -1 ? arg0.getUnderlyingValue().substring(beginIndexInt) : arg0.getUnderlyingValue().substring(beginIndexInt, endIndexInt);
}
catch (ArithmeticException | IndexOutOfBoundsException e)
} catch (ArithmeticException | IndexOutOfBoundsException e)
{
throw new IndeterminateEvaluationException(argsOutOfBoundsErrorMessage, XacmlStatusCode.PROCESSING_ERROR.value(), e);
}
......@@ -141,23 +138,21 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
this.param0Type = param0Type;
}
private static String getInvalidArg1MessagePrefix(final FirstOrderFunctionSignature<?> funcsig)
{
private static String getInvalidArg1MessagePrefix(final FirstOrderFunctionSignature<?> funcsig) {
return "Function " + funcsig.getName() + ": Invalid arg #1 (beginIndex): expected: positive integer; actual: ";
}
private static String getInvalidArg2MessagePrefix(final FirstOrderFunctionSignature<?> funcsig)
{
private static String getInvalidArg2MessagePrefix(final FirstOrderFunctionSignature<?> funcsig) {
return "Function " + funcsig.getName() + ": Invalid arg #2 (endIndex): expected: -1 or positive integer >= beginIndex; actual: ";
}
/** {@inheritDoc} */
@Override
public FirstOrderFunctionCall<StringValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes)
{
if (argExpressions.size() != 3)
public FirstOrderFunctionCall<StringValue> newCall(final List<Expression<?>> argExpressions, final Datatype<?>... remainingArgTypes) {
final int numOfArgs = argExpressions.size() + remainingArgTypes.length;
if (numOfArgs != 3)
{
throw new IllegalArgumentException("Function " + functionSignature.getName() + ": Invalid number of args: expected: 3; actual: " + argExpressions.size());
throw new IllegalArgumentException("Function " + functionSignature.getName() + ": Invalid number of args: expected: 3; actual: " + numOfArgs);
}
/*
......@@ -165,10 +160,20 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
* error
*/
final Iterator<? extends Expression<?>> argExpsIterator = argExpressions.iterator();
// Skip the first argument which is the string
if (!argExpsIterator.hasNext())
{
return new Call(functionSignature, param0Type, argExpressions, remainingArgTypes);
}
// Skip the first argument (arg #0) which is the string
argExpsIterator.next();
// Second arg
// Second arg (arg #1)
if (!argExpsIterator.hasNext())
{
return new Call(functionSignature, param0Type, argExpressions, remainingArgTypes);
}
final Expression<?> arg1Exp = argExpsIterator.next();
final Optional<? extends Value> arg1 = arg1Exp.getValue();
final int beginIndex;
......@@ -185,13 +190,17 @@ final class SubstringFunction<AV extends SimpleValue<String>> extends MultiParam
{
throw new IllegalArgumentException(getInvalidArg1MessagePrefix(functionSignature) + beginIndex);
}
}
else
} else
{
beginIndex = -1; // undefined
}
// Third arg
if (!argExpsIterator.hasNext())
{
return new Call(functionSignature, param0Type, argExpressions, remainingArgTypes);
}
final Expression<?> arg2Exp = argExpsIterator.next();
final Optional<? extends Value> arg2 = arg2Exp.getValue();
if (arg2.isPresent())
......
......@@ -66,10 +66,9 @@ public abstract class StandardFunctionTest
{
try
{
STD_EXPRESSION_FACTORY = new DepthLimitingExpressionFactory(StandardAttributeValueFactories.getRegistry(true, Optional.empty()), StandardFunction.getRegistry(true,
StandardAttributeValueFactories.BIG_INTEGER), null, 0, false, false);
}
catch (IllegalArgumentException | IOException e)
STD_EXPRESSION_FACTORY = new DepthLimitingExpressionFactory(StandardAttributeValueFactories.getRegistry(true, Optional.empty()),
StandardFunction.getRegistry(true, StandardAttributeValueFactories.BIG_INTEGER), null, 0, false, false);
} catch (IllegalArgumentException | IOException e)
{
throw new RuntimeException(e);
}
......@@ -79,7 +78,7 @@ public abstract class StandardFunctionTest
private final Value expectedResult;
private final String toString;
private final boolean areBagsComparedAsSets;
private boolean syntaxErrorRaised = false;
private boolean isTestOkBeforeFuncCall = false;
/**
* Creates instance
......@@ -101,15 +100,13 @@ public abstract class StandardFunctionTest
if (inputs.isEmpty())
{
subFuncReturnType = null;
}
else
} else
{