Commit 8b027e1c authored by cdanger's avatar cdanger
Browse files

Merge branch 'release/13.0.0'

parents 6075e6e2 aa2830b3
......@@ -7,6 +7,16 @@ All notable changes to this project are documented in this file following the [K
- 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.
## 13.0.0
### Changed
- authzforce-ce-core-pdp-api version: 15.0.0. [More info](https://github.com/authzforce/core-pdp-api/blob/develop/CHANGELOG.md#1500).
### Fixed
- pdp-testutils module depends on jongo version which depends on jackson-databind version < 2.9.5 affected by CVE-2018-7489. Fix: upgrade to 2.9.5.
- NPE in `CoreRootPolicyProvider#getInstance(...)` with null `environmentProperties` arg
- `BasePdpEngine#evaluate(IndividualDecisionRequest)` not using enabled decision cache
## 12.0.0
### Changed
- Dependency authzforce-ce-core-pdp-api: version 13.0.0 -> 14.0.0; changes APIs for PDP AttributeProvider and DecisionCache extensions:
......
......@@ -78,7 +78,7 @@ Java (JRE) 8 or later.
## Usage
### Getting started
#### CLI
Get the latest executable jar from Maven Central: groupId/artifactId = `org.ow2.authzforce`/`authzforce-ce-core-pdp-cli` and make sure you are allowed to run it (it is a fully executable JAR), e.g. with command:
Get the [latest executable jar from Maven Central](http://central.maven.org/maven2/org/ow2/authzforce/authzforce-ce-core-pdp-cli/) with groupId/artifactId = `org.ow2.authzforce`/`authzforce-ce-core-pdp-cli` and make sure you are allowed to run it (it is a fully executable JAR), e.g. with command:
```
$ chmod a+x authzforce-ce-core-pdp-cli-10.0.0.jar
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>12.0.0</version>
<version>13.0.0</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>12.0.0</version>
<version>13.0.0</version>
</dependency>
<dependency>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core-pdp-io-xacml-json</artifactId>
<version>12.0.0</version>
<version>13.0.0</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>12.0.0</version>
<version>13.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>org.ow2.authzforce</groupId>
<artifactId>authzforce-ce-core</artifactId>
<version>12.0.0</version>
<version>13.0.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>authzforce-ce-core-pdp-engine</artifactId>
......
......@@ -20,28 +20,32 @@
*/
package org.ow2.authzforce.core.pdp.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignment;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression;
import javax.xml.bind.JAXBElement;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.PepActionAttributeAssignment;
import org.ow2.authzforce.core.pdp.api.expression.Expression;
import org.ow2.authzforce.core.pdp.api.expression.ExpressionFactory;
import org.ow2.authzforce.core.pdp.api.value.AttributeValue;
import org.ow2.authzforce.core.pdp.api.value.Bag;
import org.ow2.authzforce.core.pdp.api.value.PrimitiveValue;
import org.ow2.authzforce.core.pdp.api.value.Value;
import org.ow2.authzforce.xacml.identifiers.XacmlStatusCode;
import org.ow2.authzforce.core.pdp.api.value.Datatype;
import org.ow2.authzforce.core.pdp.api.value.StandardDatatypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.ExpressionType;
/**
* XACML AttributeAssignmentExpression evaluator
*
......@@ -49,17 +53,73 @@ import com.google.common.base.Preconditions;
*/
public final class AttributeAssignmentExpressionEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(AttributeAssignmentExpressionEvaluator.class);
private static abstract class AttributeValueExpression<AV extends AttributeValue>
{
private final Datatype<AV> datatype;
private AttributeValueExpression(Datatype<AV> attributeDatatype)
{
this.datatype = attributeDatatype;
}
private final Datatype<AV> getDatatype()
{
return datatype;
}
protected abstract Collection<AV> evaluate(final EvaluationContext ctx) throws IndeterminateEvaluationException;
}
private static final class SingleAttributeValueExpression<AV extends AttributeValue> extends AttributeValueExpression<AV>
{
private final Expression<AV> valueExpr;
private SingleAttributeValueExpression(Expression<AV> valueExpression)
{
super(valueExpression.getReturnType());
this.valueExpr = valueExpression;
}
@Override
protected Collection<AV> evaluate(EvaluationContext ctx) throws IndeterminateEvaluationException
{
// atomic (see spec §5.30, 5.40) / primitive attribute value
return Collections.singleton(valueExpr.evaluate(ctx));
}
}
private static final class AttributeBagExpression<AV extends AttributeValue> extends AttributeValueExpression<AV>
{
private final Expression<? extends Bag<AV>> valueExpr;
private <B extends Bag<AV>> AttributeBagExpression(Expression<B> valueExpression)
{
super((Datatype<AV>) valueExpression.getReturnType().getTypeParameter().get());
this.valueExpr = valueExpression;
}
private final Expression<?> evaluatableExpression;
@Override
protected Collection<AV> evaluate(EvaluationContext ctx) throws IndeterminateEvaluationException
{
return valueExpr.evaluate(ctx).elements();
}
}
private static final Logger LOGGER = LoggerFactory.getLogger(AttributeAssignmentExpressionEvaluator.class);
private final String attributeId;
private final String category;
private final Optional<String> category;
private final String issuer;
private final Optional<String> issuer;
private transient volatile String toString = null; // Effective Java - Item 71
private final AttributeValueExpression<?> attValExpr;
private transient final String toString;
/**
* Instantiates evaluatable AttributeAssignment expression evaluator from XACML-Schema-derived JAXB {@link oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression}
......@@ -74,20 +134,81 @@ public final class AttributeAssignmentExpressionEvaluator
* invalid AttributeAssignmentExpression's Expression
*/
public AttributeAssignmentExpressionEvaluator(final AttributeAssignmentExpression jaxbAttrAssignExp, final XPathCompiler xPathCompiler, final ExpressionFactory expFactory)
throws IllegalArgumentException
throws IllegalArgumentException
{
/*
* Cannot used AttributeFQN class to handle metadata because AttributeAssignment Category is not required like in AttributeDesignator which is what the AttributeFQN is used for
*/
this.attributeId = Preconditions.checkNotNull(jaxbAttrAssignExp.getAttributeId(), "Undefined AttributeAssignment/AttributeId");
this.category = jaxbAttrAssignExp.getCategory();
this.issuer = jaxbAttrAssignExp.getIssuer();
this.evaluatableExpression = expFactory.getInstance(jaxbAttrAssignExp.getExpression().getValue(), xPathCompiler, null);
this.attributeId = jaxbAttrAssignExp.getAttributeId();
Preconditions.checkArgument(attributeId != null, "Undefined AttributeAssignment/AttributeId");
this.category = Optional.ofNullable(jaxbAttrAssignExp.getCategory());
this.issuer = Optional.ofNullable(jaxbAttrAssignExp.getIssuer());
this.toString = "AttributeAssignmentExpression [attributeId=" + attributeId + ", category=" + category.orElse(null) + ", issuer=" + issuer.orElse(null) + "]";
final JAXBElement<? extends ExpressionType> xacmlExpr = jaxbAttrAssignExp.getExpression();
Preconditions.checkArgument(xacmlExpr != null, "Undefined AttributeAssignment/Expression");
final Expression<?> evaluatableExpression = expFactory.getInstance(xacmlExpr.getValue(), xPathCompiler, null);
/*
* As stated in section 5.41 of XACML spec, the expression must evaluate to a constant attribute value or a bag of zero or more attribute values.
*/
final Datatype<?> expReturnType = evaluatableExpression.getReturnType();
final Optional<? extends Datatype<?>> expReturnTypeParam = expReturnType.getTypeParameter();
if (expReturnTypeParam.isPresent())
{
/*
* RexpReturnTypeParam is generic. Make sure it is a bag of AttributeValues
*/
final Datatype<?> nonNullTypeParam = expReturnTypeParam.get();
/*
* Make sure typeParam is not itself generic like a bag
*/
if (nonNullTypeParam.getTypeParameter().isPresent() || nonNullTypeParam == StandardDatatypes.FUNCTION)
{
throw new IllegalArgumentException(
"Invalid " + toString + ": invalid Expression's return type (" + expReturnType + ")'. Expected: AttributeValue or bag (of AttributeValues) datatype.");
}
/*
* So we assume that if type parameter is not Function or generic (bag), it is AttributeValue subtype and expReturnType is Bag<?> datatype. (This is not formally guaranteed :-( but can we
* do better?)
*/
this.attValExpr = new AttributeBagExpression<>((Expression<Bag>) evaluatableExpression);
} else
{
/*
* expReturnType assumed primitive (Function or AttributeValue a priori)
*/
if (expReturnType == StandardDatatypes.FUNCTION)
{
throw new IllegalArgumentException(
"Invalid " + toString + ": invalid Expression's return type (" + expReturnType + ")'. Expected: AttributeValue or bag (of AttributeValues) datatype.");
}
/*
* So we assume that if expReturnType is not Function, it is AttributeValue subtype. (This is not formally guaranteed :-( but can we do better?)
*/
this.attValExpr = new SingleAttributeValueExpression<>((Expression<? extends AttributeValue>) evaluatableExpression);
}
}
private AttributeAssignment newAttributeAssignment(final AttributeValue attrVal)
private <AV extends AttributeValue> PepActionAttributeAssignment<AV> newAttributeAssignment(Datatype<AV> datatype, final AV attrVal)
{
return new AttributeAssignment(attrVal.getContent(), attrVal.getDataType(), attrVal.getOtherAttributes(), this.attributeId, this.category, this.issuer);
return new PepActionAttributeAssignment<>(this.attributeId, this.category, this.issuer, datatype, attrVal);
}
private <AV extends AttributeValue> List<PepActionAttributeAssignment<?>> newAttributeAssignments(final AttributeValueExpression<AV> expression, final EvaluationContext context)
throws IndeterminateEvaluationException
{
final Collection<AV> vals = expression.evaluate(context);
LOGGER.debug("{}/Expression -> {}", this, vals);
/*
* vals may be empty bag, in particular if AttributeDesignator/AttributeSelector with MustBePresent=False evaluates to empty bag. Sections 5.30/5.40 of XACML core spec says:
* "If the bag is empty, there shall be no <AttributeAssignment> from this <AttributeAssignmentExpression>."
*/
return vals.stream().map(av -> newAttributeAssignment(expression.getDatatype(), av)).collect(Collectors.toList());
}
/**
......@@ -101,67 +222,15 @@ public final class AttributeAssignmentExpressionEvaluator
* @throws org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException
* if evaluation of the Expression in this context fails (Indeterminate)
*/
public List<AttributeAssignment> evaluate(final EvaluationContext context) throws IndeterminateEvaluationException
public Collection<PepActionAttributeAssignment<?>> evaluate(final EvaluationContext context) throws IndeterminateEvaluationException
{
final Value result = this.evaluatableExpression.evaluate(context);
LOGGER.debug("{}/Expression -> {}", this, result);
final List<AttributeAssignment> attrAssignList;
if (result instanceof Bag)
{
// result is a bag
final Bag<?> bag = (Bag<?>) result;
attrAssignList = new ArrayList<>(bag.size());
/*
* Bag may be empty, in particular if AttributeDesignator/AttributeSelector with MustBePresent=False evaluates to empty bag. Sections 5.30/5.40 of XACML core spec says:
* "If the bag is empty, there shall be no <AttributeAssignment> from this <AttributeAssignmentExpression>."
*/
for (final PrimitiveValue attrVal : bag)
{
if (!(attrVal instanceof AttributeValue))
{
LOGGER.error("Error evaluating {}: one of the elements in the result bag is not an AttributeValue");
throw new IndeterminateEvaluationException("Error evaluating " + this, XacmlStatusCode.PROCESSING_ERROR.value());
}
attrAssignList.add(newAttributeAssignment((AttributeValue) attrVal));
}
}
else if (result instanceof AttributeValue)
{
// atomic (see spec §5.30, 5.40) / primitive attribute value
attrAssignList = Collections.singletonList(newAttributeAssignment((AttributeValue) result));
}
else
{
LOGGER.error("Error evaluating {}: the result value is not an AttributeValue");
throw new IndeterminateEvaluationException("Error evaluating " + this, XacmlStatusCode.PROCESSING_ERROR.value());
}
return attrAssignList;
return newAttributeAssignments(this.attValExpr, context);
}
@Override
public String toString()
{
if (toString == null)
{
toString = "AttributeAssignmentExpression [attributeId=" + attributeId + ", category=" + category + ", issuer=" + issuer + "]";
}
return toString;
}
// public static void main(String[] args) throws JAXBException
// {
// THIS WILL FAIL: com.sun.istack.internal.SAXException2: unable to marshal type "java.lang.Double" as an element
// because it is missing an
// @XmlRootElement annotation; but it succeeds with java.lang.String
// final AttributeAssignment attrAssignment = new AttributeAssignment(Collections.<Serializable>
// singletonList("1.0"), "mytype", null, "myattribute1",
// "mycategory", null);
//
// Marshaller marshaller = XACMLBindingUtils.createXacml3Marshaller();
// marshaller.marshal(attrAssignment, System.out);
// }
}
......@@ -164,6 +164,8 @@ public final class BasePdpEngine implements CloseablePdpEngine
@Override
public Bag<?> putNamedAttributeIfAbsent(final AttributeFqn attributeFqn, final AttributeBag<?> attributeValues)
{
assert attributeFqn != null;
/*
* Put the non-issued version of the attribute first
*/
......@@ -180,7 +182,6 @@ public final class BasePdpEngine implements CloseablePdpEngine
*/
private static abstract class IndividualDecisionRequestEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(IndividualDecisionRequestEvaluator.class);
private interface RequestAndPdpIssuedNamedAttributesMerger
{
......@@ -356,10 +357,18 @@ public final class BasePdpEngine implements CloseablePdpEngine
protected final EvaluationContext newEvaluationContext(final DecisionRequest request, final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes)
{
assert request != null;
final Map<AttributeFqn, AttributeBag<?>> mergedNamedAttributes = reqAndPdpIssuedAttributesMerger.merge(pdpIssuedAttributes, request.getNamedAttributes());
return new IndividualDecisionRequestContext(mergedNamedAttributes, request.getExtraContentsByCategory(), request.isApplicablePolicyIdListReturned());
}
protected final DecisionResult evaluateInNewContext(final DecisionRequest request, final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes)
{
assert request != null;
final EvaluationContext evalCtx = newEvaluationContext(request, pdpIssuedAttributes);
return rootPolicyEvaluator.findAndEvaluate(evalCtx);
}
/**
* <p>
* Evaluate Individual Decision Request in an existing request context
......@@ -379,19 +388,13 @@ public final class BasePdpEngine implements CloseablePdpEngine
* Evaluate an Individual Decision Request from which a new request context is created to evaluate the request
* </p>
*
* @param request
* a non-null {@link DecisionRequest} object.
* @param individualDecisionRequest
* a non-null {@link DecisionRequest} object, i.e. representation of Individual Decision Request (as defined by Multiple Decision Profile of XACML).
* @param pdpIssuedAttributes
* a {@link java.util.Map} of PDP-issued attributes including at least the standard environment attributes: current-time, current-date, current-dateTime.
* @return the evaluation result.
*/
protected final DecisionResult evaluateInNewContext(final DecisionRequest request, final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes)
{
assert request != null;
LOGGER.debug("Evaluating Individual Decision Request: {}", request);
final EvaluationContext evalCtx = newEvaluationContext(request, pdpIssuedAttributes);
return rootPolicyEvaluator.findAndEvaluate(evalCtx);
}
protected abstract DecisionResult evaluate(final DecisionRequest individualDecisionRequest, final StandardEnvironmentAttributeIssuer pdpStdEnvAttributeIssuer);
/**
* <p>
......@@ -400,19 +403,21 @@ public final class BasePdpEngine implements CloseablePdpEngine
*
* @param individualDecisionRequests
* a {@link java.util.List} of individual decision requests.
* @param pdpIssuedAttributes
* @param pdpStdEnvAttributeIssuer
* a {@link java.util.Map} of PDP-issued attributes including at least the standard environment attributes: current-time, current-date, current-dateTime.
* @return individual decision request-result pairs, where the list of the requests is the same as {@code individualDecisionRequests}.
* @throws IndeterminateEvaluationException
* if an error occurred preventing any request evaluation
*/
protected abstract <INDIVIDUAL_DECISION_REQ_T extends DecisionRequest> Collection<Entry<INDIVIDUAL_DECISION_REQ_T, ? extends DecisionResult>> evaluate(
List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests, final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes) throws IndeterminateEvaluationException;
List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests, final StandardEnvironmentAttributeIssuer pdpStdEnvAttributeIssuer) throws IndeterminateEvaluationException;
}
private static final class NonCachingIndividualDecisionRequestEvaluator extends IndividualDecisionRequestEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(NonCachingIndividualDecisionRequestEvaluator.class);
private static final RuntimeException NULL_INDIVIDUAL_DECISION_REQUEST_EXCEPTION = new RuntimeException(
"One of the individual decision requests returned by the request filter is invalid (null).");
......@@ -421,12 +426,21 @@ public final class BasePdpEngine implements CloseablePdpEngine
super(rootPolicyEvaluator, stdEnvAttributeSource);
}
@Override
protected DecisionResult evaluate(DecisionRequest request, StandardEnvironmentAttributeIssuer pdpStdEnvAttributeIssuer)
{
assert request != null;
LOGGER.debug("Evaluating Individual Decision Request: {}", request);
return evaluateInNewContext(request, pdpStdEnvAttributeIssuer.get());
}
@Override
protected <INDIVIDUAL_DECISION_REQ_T extends DecisionRequest> Collection<Entry<INDIVIDUAL_DECISION_REQ_T, ? extends DecisionResult>> evaluate(
final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests, final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes) throws IndeterminateEvaluationException
final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests, final StandardEnvironmentAttributeIssuer pdpStdEnvAttributeIssuer) throws IndeterminateEvaluationException
{
assert individualDecisionRequests != null;
assert individualDecisionRequests != null && pdpStdEnvAttributeIssuer != null;
final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes = pdpStdEnvAttributeIssuer.get();
final Collection<Entry<INDIVIDUAL_DECISION_REQ_T, ? extends DecisionResult>> resultsByRequest = new ArrayDeque<>(individualDecisionRequests.size());
for (final INDIVIDUAL_DECISION_REQ_T individualDecisionRequest : individualDecisionRequests)
{
......@@ -444,45 +458,57 @@ public final class BasePdpEngine implements CloseablePdpEngine
}
private static abstract class CachingIndividualRequestEvaluator extends IndividualDecisionRequestEvaluator
private static final class IndividualRequestEvaluatorWithCacheIgnoringEvaluationContext extends IndividualDecisionRequestEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(IndividualRequestEvaluatorWithCacheIgnoringEvaluationContext.class);
protected static final IndeterminateEvaluationException INDETERMINATE_EVALUATION_EXCEPTION = new IndeterminateEvaluationException("Internal error in decision cache: null result",
private static final IndeterminateEvaluationException INDETERMINATE_EVALUATION_EXCEPTION = new IndeterminateEvaluationException("Internal error in decision cache: null result",
XacmlStatusCode.PROCESSING_ERROR.value());
protected final DecisionCache decisionCache;
private final DecisionCache decisionCache;
private CachingIndividualRequestEvaluator(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource stdEnvAttributeSource, final DecisionCache decisionCache)
private IndividualRequestEvaluatorWithCacheIgnoringEvaluationContext(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource stdEnvAttributeSource,
final DecisionCache decisionCache)
{
super(rootPolicyEvaluator, stdEnvAttributeSource);
assert decisionCache != null;
this.decisionCache = decisionCache;
}
}
private static final class IndividualRequestEvaluatorWithCacheIgnoringEvaluationContext extends CachingIndividualRequestEvaluator
{
// the logger we'll use for all messages
private static final Logger _LOGGER = LoggerFactory.getLogger(IndividualRequestEvaluatorWithCacheIgnoringEvaluationContext.class);
private IndividualRequestEvaluatorWithCacheIgnoringEvaluationContext(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource stdEnvAttributeSource,
final DecisionCache decisionCache)
@Override
protected DecisionResult evaluate(DecisionRequest individualDecisionRequest, StandardEnvironmentAttributeIssuer pdpStdEnvAttributeIssuer)
{
super(rootPolicyEvaluator, stdEnvAttributeSource, decisionCache);
assert individualDecisionRequest != null;
LOGGER.debug("Evaluating Individual Decision Request: {}", individualDecisionRequest);
final DecisionResult cachedResult = decisionCache.get(individualDecisionRequest, null);
if (cachedResult == null)
{
LOGGER.debug("No result found in cache for Individual Decision Request: {}. Computing new result from policy evaluation...", individualDecisionRequest);
final DecisionResult newResult = evaluateInNewContext(individualDecisionRequest, pdpStdEnvAttributeIssuer.get());
LOGGER.debug("Caching new Result for Individual Decision Request: {} -> {}", individualDecisionRequest, newResult);
decisionCache.put(individualDecisionRequest, newResult, null);
return newResult;
}
LOGGER.debug("Result found in cache for Individual Decision Request: {} -> {}", individualDecisionRequest, cachedResult);
return cachedResult;
}
@Override
public <INDIVIDUAL_DECISION_REQ_T extends DecisionRequest> Collection<Entry<INDIVIDUAL_DECISION_REQ_T, ? extends DecisionResult>> evaluate(
final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests, final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes) throws IndeterminateEvaluationException
protected <INDIVIDUAL_DECISION_REQ_T extends DecisionRequest> Collection<Entry<INDIVIDUAL_DECISION_REQ_T, ? extends DecisionResult>> evaluate(
final List<INDIVIDUAL_DECISION_REQ_T> individualDecisionRequests, final StandardEnvironmentAttributeIssuer pdpStdEnvAttributeIssuer) throws IndeterminateEvaluationException
{
assert individualDecisionRequests != null && pdpStdEnvAttributeIssuer != null;
final Map<INDIVIDUAL_DECISION_REQ_T, DecisionResult> cachedResultsByRequest = decisionCache.getAll(individualDecisionRequests);
if (cachedResultsByRequest == null)
{
// error, return indeterminate result as only result
_LOGGER.error("Invalid decision cache result: null");
LOGGER.error("Invalid decision cache result: null");
throw INDETERMINATE_EVALUATION_EXCEPTION;
}
final Map<AttributeFqn, AttributeBag<?>> pdpIssuedAttributes = pdpStdEnvAttributeIssuer.get();
/*
* There will be at most as many new results (not in cache) as there are individual decision requests
*/
......@@ -490,6 +516,7 @@ public final class BasePdpEngine implements CloseablePdpEngine
final Map<INDIVIDUAL_DECISION_REQ_T, DecisionResult> newResultsByRequest = HashCollections.newUpdatableMap(individualDecisionRequests.size());
for (final INDIVIDUAL_DECISION_REQ_T individualDecisionRequest : individualDecisionRequests)
{
LOGGER.debug("Evaluating Individual Decision Request: {}", individualDecisionRequest);
final DecisionResult finalResult;
/*
* Check whether there is any decision result in cache for this request
......@@ -497,12 +524,15 @@ public final class BasePdpEngine implements CloseablePdpEngine
final DecisionResult cachedResult = cachedResultsByRequest.get(individualDecisionRequest);
if (cachedResult == null)
{
// result not in cache -> evaluate request
LOGGER.debug("No result found in cache for Individual Decision Request: {}. Computing new result from policy evaluation...", individualDecisionRequest);
finalResult = evaluateInNewContext(individualDecisionRequest, pdpIssuedAttributes);
LOGGER.debug("Caching new Result for Individual Decision Request: {} -> {}", individualDecisionRequest, finalResult);
newResultsByRequest.put(individualDecisionRequest, finalResult);
}
else
{
LOGGER.debug("Result found in cache for Individual Decision Request: {} -> {}", individualDecisionRequest, cachedResult);
finalResult = cachedResult;
}
......@@ -519,38 +549,57 @@ public final class BasePdpEngine implements CloseablePdpEngine
}
private static final class IndividualRequestEvaluatorWithCacheUsingEvaluationContext extends CachingIndividualRequestEvaluator
private static final class IndividualRequestEvaluatorWithCacheUsingEvaluationContext extends IndividualDecisionRequestEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(IndividualRequestEvaluatorWithCacheUsingEvaluationContext.class);
private final DecisionCache decisionCache;
public IndividualRequestEvaluatorWithCacheUsingEvaluationContext(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource validStdEnvAttrSrc,
private IndividualRequestEvaluatorWithCacheUsingEvaluationContext(final RootPolicyEvaluator rootPolicyEvaluator, final StandardEnvironmentAttributeSource validStdEnvAttrSrc,
final DecisionCache decisionCache)
{
super(rootPolicyEvaluator, validStdEnvAttrSrc, decisionCache);
super(rootPolicyEvaluator, validStdEnvAttrSrc);
assert decisionCache != null;
this.decisionCache = decisionCache;
<