Commit 6aa7d024 authored by cdanger's avatar cdanger

- Upgraded core-pdp-api version to 5.0.0 allowing to pass new parameter

for global PDP environment properties to Attribute Provider extensions
parent 7e53a04b
# Change log
All notable changes to this project are documented in this file following the [Keep a CHANGELOG](http://keepachangelog.com) conventions.
## Unreleased
## 4.0.2
### Fixed
- Issues reported by Codacyi (including fixed issues in upgraded dependency core-pdp-api 4.0.2)
......
......@@ -43,7 +43,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${artifactId.prefix}-core-pdp-api</artifactId>
<version>4.0.2</version>
<version>5.0.0</version>
</dependency>
<!-- /Authzforce dependencies -->
......
......@@ -33,77 +33,71 @@ import org.ow2.authzforce.core.pdp.api.AttributeGUID;
import org.ow2.authzforce.core.pdp.api.AttributeProvider;
import org.ow2.authzforce.core.pdp.api.AttributeProviderModule;
import org.ow2.authzforce.core.pdp.api.CloseableAttributeProviderModule;
import org.ow2.authzforce.core.pdp.api.EnvironmentProperties;
import org.ow2.authzforce.core.pdp.api.value.DatatypeFactoryRegistry;
import org.ow2.authzforce.xmlns.pdp.ext.AbstractAttributeProvider;
/**
* Closeable AttributeProvider
* <p>
* The sub-modules may very likely hold resources such as network resources to get attributes remotely, or attribute caches to speed up finding, etc. Therefore, you are required to call
* {@link #close()} when you no longer need an instance - especially before replacing with a new instance (with different modules) - in order to make sure these resources are released properly by each
* underlying module (e.g. close the attribute caches).
* The sub-modules may very likely hold resources such as network resources to
* get attributes remotely, or attribute caches to speed up finding, etc.
* Therefore, you are required to call {@link #close()} when you no longer need
* an instance - especially before replacing with a new instance (with different
* modules) - in order to make sure these resources are released properly by
* each underlying module (e.g. close the attribute caches).
*
* @version $Id: $
*/
public final class CloseableAttributeProvider extends ModularAttributeProvider implements Closeable
{
public final class CloseableAttributeProvider extends ModularAttributeProvider implements Closeable {
private static class ModuleAdapter
{
private static class ModuleAdapter {
private CloseableAttributeProviderModule module;
private ModuleAdapter(CloseableAttributeProviderModule module) throws IOException
{
private ModuleAdapter(CloseableAttributeProviderModule module) throws IOException {
final Set<AttributeDesignatorType> providedAttributes = module.getProvidedAttributes();
if (providedAttributes == null || providedAttributes.isEmpty())
{
if (providedAttributes == null || providedAttributes.isEmpty()) {
module.close();
throw new IllegalArgumentException("Invalid " + module + " : list of supported AttributeDesignators is null or empty");
throw new IllegalArgumentException(
"Invalid " + module + " : list of supported AttributeDesignators is null or empty");
}
this.module = module;
}
private void close() throws IOException
{
private void close() throws IOException {
this.module.close();
}
private Set<AttributeDesignatorType> getProvidedAttributes()
{
private Set<AttributeDesignatorType> getProvidedAttributes() {
return this.module.getProvidedAttributes();
}
@Override
public String toString()
{
public String toString() {
return module.toString();
}
private AttributeProviderModule getAdaptedModule()
{
private AttributeProviderModule getAdaptedModule() {
return this.module;
}
}
private static void close(Set<ModuleAdapter> moduleClosers) throws IOException
{
// An error occuring on closing one module should not stop from closing the others
// But we keep the exception in memory if any, to throw it at the end as we do not want to hide that an error occurred
private static void close(Set<ModuleAdapter> moduleClosers) throws IOException {
// An error occuring on closing one module should not stop from closing
// the others
// But we keep the exception in memory if any, to throw it at the end as
// we do not want to hide that an error occurred
IOException latestEx = null;
for (final ModuleAdapter mod : moduleClosers)
{
try
{
for (final ModuleAdapter mod : moduleClosers) {
try {
mod.close();
} catch (IOException e)
{
} catch (IOException e) {
latestEx = e;
}
}
if (latestEx != null)
{
if (latestEx != null) {
throw latestEx;
}
}
......@@ -111,95 +105,118 @@ public final class CloseableAttributeProvider extends ModularAttributeProvider i
private Set<ModuleAdapter> moduleClosers;
/**
* Instantiates attribute Provider that tries to find attribute values in evaluation context, then, if not there, query the {@code module} providing the requested attribute ID, if any.
* Instantiates attribute Provider that tries to find attribute values in
* evaluation context, then, if not there, query the {@code module}
* providing the requested attribute ID, if any.
*
* @param attributeFactory
* (mandatory) attribute value factory
*
* @param jaxbAttributeProviderConfs
* (optional) XML/JAXB configurations of Attribute Providers for AttributeDesignator/AttributeSelector evaluation; may be null for static expression evaluation (out of context), in
* which case AttributeSelectors/AttributeDesignators are not supported
* (optional) XML/JAXB configurations of Attribute Providers for
* AttributeDesignator/AttributeSelector evaluation; may be null
* for static expression evaluation (out of context), in which
* case AttributeSelectors/AttributeDesignators are not supported
* @throws IllegalArgumentException
* If any of attribute Provider modules created from {@code jaxbAttributeProviderConfs} does not provide any attribute; or it is in conflict with another one already registered to
* provide the same or part of the same attributes.
* If any of attribute Provider modules created from
* {@code jaxbAttributeProviderConfs} does not provide any
* attribute; or it is in conflict with another one already
* registered to provide the same or part of the same
* attributes.
* @throws IOException
* error closing the attribute Provider modules created from {@code jaxbAttributeProviderConfs}, when and before an {@link IllegalArgumentException} is raised
* error closing the attribute Provider modules created from
* {@code jaxbAttributeProviderConfs}, when and before an
* {@link IllegalArgumentException} is raised
*/
private CloseableAttributeProvider(Map<AttributeGUID, AttributeProviderModule> modulesByAttributeId, Set<ModuleAdapter> moduleClosers) throws IOException
{
private CloseableAttributeProvider(Map<AttributeGUID, AttributeProviderModule> modulesByAttributeId,
Set<ModuleAdapter> moduleClosers) throws IOException {
super(modulesByAttributeId);
this.moduleClosers = moduleClosers;
}
/**
* Instantiates attribute Provider that tries to find attribute values in evaluation context, then, if not there, query the {@code module} providing the requested attribute ID, if any.
* Instantiates attribute Provider that tries to find attribute values in
* evaluation context, then, if not there, query the {@code module}
* providing the requested attribute ID, if any.
*
* @param attributeFactory
* (mandatory) attribute value factory
* @param jaxbAttributeProviderConfs
* (optional) XML/JAXB configurations of Attribute Providers for AttributeDesignator/AttributeSelector evaluation; may be null for static expression evaluation (out of context), in
* which case AttributeSelectors/AttributeDesignators are not supported
* (optional) XML/JAXB configurations of Attribute Providers for
* AttributeDesignator/AttributeSelector evaluation; may be null
* for static expression evaluation (out of context), in which
* case AttributeSelectors/AttributeDesignators are not supported
* @param environmentProperties
* global PDP configuration environment properties
* @return instance of this class
* @throws java.lang.IllegalArgumentException
* If any of attribute Provider modules created from {@code jaxbAttributeProviderConfs} does not provide any attribute; or it is in conflict with another one already registered to
* provide the same or part of the same attributes.
* If any of attribute Provider modules created from
* {@code jaxbAttributeProviderConfs} does not provide any
* attribute; or it is in conflict with another one already
* registered to provide the same or part of the same
* attributes.
* @throws java.io.IOException
* error closing the attribute Provider modules created from {@code jaxbAttributeProviderConfs}, when and before an {@link IllegalArgumentException} is raised
* error closing the attribute Provider modules created from
* {@code jaxbAttributeProviderConfs}, when and before an
* {@link IllegalArgumentException} is raised
*/
public static CloseableAttributeProvider getInstance(List<AbstractAttributeProvider> jaxbAttributeProviderConfs, DatatypeFactoryRegistry attributeFactory) throws IOException
{
public static CloseableAttributeProvider getInstance(List<AbstractAttributeProvider> jaxbAttributeProviderConfs,
DatatypeFactoryRegistry attributeFactory, EnvironmentProperties environmentProperties) throws IOException {
final Map<AttributeGUID, AttributeProviderModule> modulesByAttributeId;
final Set<ModuleAdapter> moduleCloserSet;
if (jaxbAttributeProviderConfs == null)
{
if (jaxbAttributeProviderConfs == null) {
modulesByAttributeId = null;
moduleCloserSet = null;
} else
{
} else {
final int moduleCount = jaxbAttributeProviderConfs.size();
modulesByAttributeId = new HashMap<>(moduleCount);
moduleCloserSet = new HashSet<>(moduleCount);
for (final AbstractAttributeProvider jaxbAttributeProviderConf : jaxbAttributeProviderConfs)
{
try
{
final CloseableAttributeProviderModule.FactoryBuilder<AbstractAttributeProvider> attrProviderModBuilder = PdpExtensionLoader.getJaxbBoundExtension(
CloseableAttributeProviderModule.FactoryBuilder.class, jaxbAttributeProviderConf.getClass());
final CloseableAttributeProviderModule.DependencyAwareFactory depAwareAttrProviderModBuilder = attrProviderModBuilder.getInstance(jaxbAttributeProviderConf);
for (final AbstractAttributeProvider jaxbAttributeProviderConf : jaxbAttributeProviderConfs) {
try {
final CloseableAttributeProviderModule.FactoryBuilder<AbstractAttributeProvider> attrProviderModBuilder = PdpExtensionLoader
.getJaxbBoundExtension(CloseableAttributeProviderModule.FactoryBuilder.class,
jaxbAttributeProviderConf.getClass());
final CloseableAttributeProviderModule.DependencyAwareFactory depAwareAttrProviderModBuilder = attrProviderModBuilder
.getInstance(jaxbAttributeProviderConf, environmentProperties);
final Set<AttributeDesignatorType> requiredAttrs = depAwareAttrProviderModBuilder.getDependencies();
/*
* Each AttributeProviderModule is given a read-only AttributeProvider - aka "dependency attribute Provider" - to find any attribute they require (dependency), based on the
* attribute Provider modules that provide these required attributes (set above); read-only so that modules use this attribute Provider only to get required attributes, nothing
* else. Create this dependency attribute Provider.
* Each AttributeProviderModule is given a read-only
* AttributeProvider - aka "dependency attribute Provider" -
* to find any attribute they require (dependency), based on
* the attribute Provider modules that provide these
* required attributes (set above); read-only so that
* modules use this attribute Provider only to get required
* attributes, nothing else. Create this dependency
* attribute Provider.
*/
final AttributeProvider depAttrProvider;
if (requiredAttrs == null)
{
if (requiredAttrs == null) {
depAttrProvider = new ModularAttributeProvider(null);
} else
{
} else {
final Map<AttributeGUID, AttributeProviderModule> immutableCopyOfAttrProviderModsByAttrId = Collections
.<AttributeGUID, AttributeProviderModule> unmodifiableMap(modulesByAttributeId);
depAttrProvider = new ModularAttributeProvider(immutableCopyOfAttrProviderModsByAttrId, requiredAttrs);
depAttrProvider = new ModularAttributeProvider(immutableCopyOfAttrProviderModsByAttrId,
requiredAttrs);
}
// attrProviderMod closing isn't done in this method but handled in close() method when closing all modules
final ModuleAdapter moduleAdapter = new ModuleAdapter(depAwareAttrProviderModBuilder.getInstance(attributeFactory, depAttrProvider));
// attrProviderMod closing isn't done in this method but
// handled in close() method when closing all modules
final ModuleAdapter moduleAdapter = new ModuleAdapter(
depAwareAttrProviderModBuilder.getInstance(attributeFactory, depAttrProvider));
moduleCloserSet.add(moduleAdapter);
for (final AttributeDesignatorType attrDesignator : moduleAdapter.getProvidedAttributes())
{
for (final AttributeDesignatorType attrDesignator : moduleAdapter.getProvidedAttributes()) {
final AttributeGUID attrGUID = new AttributeGUID(attrDesignator);
if (modulesByAttributeId.containsKey(attrGUID))
{
if (modulesByAttributeId.containsKey(attrGUID)) {
moduleAdapter.close();
throw new IllegalArgumentException("Conflict: " + moduleAdapter + " providing the same AttributeDesignator (" + attrGUID + ") as another already registered.");
throw new IllegalArgumentException(
"Conflict: " + moduleAdapter + " providing the same AttributeDesignator ("
+ attrGUID + ") as another already registered.");
}
modulesByAttributeId.put(attrGUID, moduleAdapter.getAdaptedModule());
}
} catch (IllegalArgumentException e)
{
} catch (IllegalArgumentException e) {
close(moduleCloserSet);
throw e;
}
......@@ -211,8 +228,7 @@ public final class CloseableAttributeProvider extends ModularAttributeProvider i
/** {@inheritDoc} */
@Override
public void close() throws IOException
{
public void close() throws IOException {
close(this.moduleClosers);
}
}
......@@ -37,6 +37,7 @@ import oasis.names.tc.xacml._3_0.core.schema.wd_17.FunctionType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableDefinition;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
import org.ow2.authzforce.core.pdp.api.EnvironmentProperties;
import org.ow2.authzforce.core.pdp.api.expression.BaseVariableReference;
import org.ow2.authzforce.core.pdp.api.expression.Expression;
import org.ow2.authzforce.core.pdp.api.expression.ExpressionFactory;
......@@ -54,24 +55,31 @@ import org.ow2.authzforce.xmlns.pdp.ext.AbstractAttributeProvider;
import com.sun.xacml.UnknownIdentifierException;
/**
* Implementation of ExpressionFactory that supports the Expressions defined in VariableDefinitions in order to resolve VariableReferences. In particular, it makes sure the depth of recursivity of
* VariableDefinition does not exceed a value (to avoid inconveniences such as stackoverflow or very negative performance impact) defined by parameter to
* {@link #ExpressionFactoryImpl(DatatypeFactoryRegistry, FunctionRegistry, List, int, boolean, boolean)} parameter. Note that reference loops are avoided by the fact that a VariableReference can
* reference only a VariableDefinition defined previously to the VariableReference in this implementation.
* Implementation of ExpressionFactory that supports the Expressions defined in
* VariableDefinitions in order to resolve VariableReferences. In particular, it
* makes sure the depth of recursivity of VariableDefinition does not exceed a
* value (to avoid inconveniences such as stackoverflow or very negative
* performance impact) defined by parameter to
* {@link #ExpressionFactoryImpl(DatatypeFactoryRegistry, FunctionRegistry, List, int, boolean, boolean)}
* parameter. Note that reference loops are avoided by the fact that a
* VariableReference can reference only a VariableDefinition defined previously
* to the VariableReference in this implementation.
*
*
* @version $Id: $
*/
public class ExpressionFactoryImpl implements ExpressionFactory
{
public class ExpressionFactoryImpl implements ExpressionFactory {
private static final IllegalArgumentException MISSING_ATTRIBUTE_DESIGNATOR_ISSUER_EXCEPTION = new IllegalArgumentException(
"Missing Issuer that is required on AttributeDesignators by PDP configuration");
private static final IllegalArgumentException UNSUPPORTED_ATTRIBUTE_SELECTOR_EXCEPTION = new IllegalArgumentException("Unsupported Expression type (optional XACML feature): AttributeSelector");
private static final IllegalArgumentException UNSUPPORTED_ATTRIBUTE_SELECTOR_EXCEPTION = new IllegalArgumentException(
"Unsupported Expression type (optional XACML feature): AttributeSelector");
private static final IllegalArgumentException NULL_FUNCTION_REGISTRY_EXCEPTION = new IllegalArgumentException("Undefined function registry");
private static final IllegalArgumentException NULL_FUNCTION_REGISTRY_EXCEPTION = new IllegalArgumentException(
"Undefined function registry");
private static final IllegalArgumentException NULL_ATTRIBUTE_DATATYPE_REGISTRY_EXCEPTION = new IllegalArgumentException("Undefined attribute datatype registry");
private static final IllegalArgumentException NULL_ATTRIBUTE_DATATYPE_REGISTRY_EXCEPTION = new IllegalArgumentException(
"Undefined attribute datatype registry");
private static final IllegalArgumentException UNSUPPORTED_ATTRIBUTE_DESIGNATOR_OR_SELECTOR_BECAUSE_OF_NULL_ATTRIBUTE_PROVIDER_EXCEPTION = new IllegalArgumentException(
"Unsupported Expression type 'AttributeDesignator' and 'AttributeSelector' because no attribute Provider defined");
......@@ -89,10 +97,14 @@ public class ExpressionFactoryImpl implements ExpressionFactory
private final boolean issuerRequiredOnAttributeDesignators;
/**
* Maximum VariableReference depth allowed for VariableDefinitions to be managed. Examples:
* Maximum VariableReference depth allowed for VariableDefinitions to be
* managed. Examples:
* <ul>
* <li>A VariableDefinition V1 that does not use any VariableReference has a reference depth of 0.</li>
* <li>A VariableDefinition V1 that uses a VariableReference to VariableDefinition V2 with no further VariableReference, has a reference depth of 1</li>
* <li>A VariableDefinition V1 that does not use any VariableReference has a
* reference depth of 0.</li>
* <li>A VariableDefinition V1 that uses a VariableReference to
* VariableDefinition V2 with no further VariableReference, has a reference
* depth of 1</li>
* <li>etc.</li>
* </ul>
*
......@@ -101,34 +113,52 @@ public class ExpressionFactoryImpl implements ExpressionFactory
* @param functionRegistry
* function registry (not null)
* @param jaxbAttributeProviderConfs
* XML/JAXB configurations of Attribute Providers for AttributeDesignator/AttributeSelector evaluation; may be null for static expression evaluation (out of context), in which case
* AttributeSelectors/AttributeDesignators are not supported
* XML/JAXB configurations of Attribute Providers for
* AttributeDesignator/AttributeSelector evaluation; may be null
* for static expression evaluation (out of context), in which
* case AttributeSelectors/AttributeDesignators are not supported
* @param maxVarRefDepth
* max depth of VariableReference chaining: VariableDefinition -> VariableDefinition ->... ('->' represents a VariableReference); strictly negative value means unlimited
* max depth of VariableReference chaining: VariableDefinition ->
* VariableDefinition ->... ('->' represents a
* VariableReference); strictly negative value means unlimited
* @param allowAttributeSelectors
* allow use of AttributeSelectors (experimental, not for production, use with caution)
* allow use of AttributeSelectors (experimental, not for
* production, use with caution)
* @param issuerRequiredInAttributeDesignators
* true iff it is required that all AttributeDesignator set the Issuer field, as a best practice. If the issuer is not set, remember what XACML 3.0 AttributeDesignator Evaluation says:
* true iff it is required that all AttributeDesignator set the
* Issuer field, as a best practice. If the issuer is not set,
* remember what XACML 3.0 AttributeDesignator Evaluation says:
* "If the Issuer is not present in the attribute designator, then the matching of the attribute to the named attribute SHALL be governed by AttributeId and DataType attributes alone."
* As a result, be aware that if you use AttributeDesignators without Issuer ( {@code issuerRequiredInAttributeDesignators == false}) and the requests are using matching Attributes but
* with one or more different Issuers, this PDP engine has to gather all the values from all the attributes with matching Category/AttributeId but with any Issuer or no Issuer,
* As a result, be aware that if you use AttributeDesignators
* without Issuer (
* {@code issuerRequiredInAttributeDesignators == false}) and the
* requests are using matching Attributes but with one or more
* different Issuers, this PDP engine has to gather all the
* values from all the attributes with matching
* Category/AttributeId but with any Issuer or no Issuer,
* resulting in lower performance.
* @param environmentProperties
* global PDP configuration environment properties
* @throws java.lang.IllegalArgumentException
* If any of attribute Provider modules created from {@code jaxbAttributeProviderConfs} does not provide any attribute; or it is in conflict with another one already registered to
* provide the same or part of the same attributes.
* If any of attribute Provider modules created from
* {@code jaxbAttributeProviderConfs} does not provide any
* attribute; or it is in conflict with another one already
* registered to provide the same or part of the same
* attributes.
* @throws java.io.IOException
* error closing the attribute Provider modules created from {@code jaxbAttributeProviderConfs}, when and before an {@link IllegalArgumentException} is raised
* error closing the attribute Provider modules created from
* {@code jaxbAttributeProviderConfs}, when and before an
* {@link IllegalArgumentException} is raised
*/
public ExpressionFactoryImpl(DatatypeFactoryRegistry attributeFactory, FunctionRegistry functionRegistry, List<AbstractAttributeProvider> jaxbAttributeProviderConfs, int maxVarRefDepth,
boolean allowAttributeSelectors, boolean issuerRequiredInAttributeDesignators) throws IllegalArgumentException, IOException
{
if (attributeFactory == null)
{
public ExpressionFactoryImpl(DatatypeFactoryRegistry attributeFactory, FunctionRegistry functionRegistry,
List<AbstractAttributeProvider> jaxbAttributeProviderConfs, int maxVarRefDepth,
boolean allowAttributeSelectors, boolean issuerRequiredInAttributeDesignators,
EnvironmentProperties environmentProperties) throws IllegalArgumentException, IOException {
if (attributeFactory == null) {
throw NULL_ATTRIBUTE_DATATYPE_REGISTRY_EXCEPTION;
}
if (functionRegistry == null)
{
if (functionRegistry == null) {
throw NULL_FUNCTION_REGISTRY_EXCEPTION;
}
......@@ -137,27 +167,37 @@ public class ExpressionFactoryImpl implements ExpressionFactory
this.maxVariableReferenceDepth = maxVarRefDepth < 0 ? UNLIMITED_MAX_VARIABLE_REF_DEPTH : maxVarRefDepth;
// finally create the global attribute Provider used to resolve
// AttributeDesignators
this.attributeProvider = CloseableAttributeProvider.getInstance(jaxbAttributeProviderConfs, attributeFactory);
this.attributeProvider = CloseableAttributeProvider.getInstance(jaxbAttributeProviderConfs, attributeFactory,
environmentProperties);
this.allowAttributeSelectors = allowAttributeSelectors;
this.issuerRequiredOnAttributeDesignators = issuerRequiredInAttributeDesignators;
}
/** {@inheritDoc} */
@Override
public VariableReference<?> addVariable(VariableDefinition varDef, XPathCompiler xPathCompiler, Deque<String> inoutLongestVarRefChain) throws IllegalArgumentException
{
public VariableReference<?> addVariable(VariableDefinition varDef, XPathCompiler xPathCompiler,
Deque<String> inoutLongestVarRefChain) throws IllegalArgumentException {
final String varId = varDef.getVariableId();
/*
* Initialize the longest variable reference chain from this VariableDefinition (varDef -> VarDef2 -> ..., where "v1 -> v2" means: v1's expression contains a VariableReference to v2) as empty
* for later update by this#getDefinition() when resolving a VariableReference within this varDef's expression (being parsed just after). The goal is to detect chains longer than
* this.maxVariableReferenceDepth to limit abuse of VariableReferences. There may be multiple VariableReferences in a VariableDefinition's expression, such as an Apply, and each may be
* referencing a different VariableDefinition; but we are interested only in the one with the longest chain of references.
* Initialize the longest variable reference chain from this
* VariableDefinition (varDef -> VarDef2 -> ..., where "v1 -> v2" means:
* v1's expression contains a VariableReference to v2) as empty for
* later update by this#getDefinition() when resolving a
* VariableReference within this varDef's expression (being parsed just
* after). The goal is to detect chains longer than
* this.maxVariableReferenceDepth to limit abuse of VariableReferences.
* There may be multiple VariableReferences in a VariableDefinition's
* expression, such as an Apply, and each may be referencing a different
* VariableDefinition; but we are interested only in the one with the
* longest chain of references.
*/
/*
* we need to check the longest variableReference chain does not have circular reference and does not exceed a specific value (need to call contains() method repeatedly and preserve the
* order).
* we need to check the longest variableReference chain does not have
* circular reference and does not exceed a specific value (need to call
* contains() method repeatedly and preserve the order).
*/
final Deque<String> longestVarRefChain = inoutLongestVarRefChain == null ? new ArrayDeque<String>() : inoutLongestVarRefChain;
final Deque<String> longestVarRefChain = inoutLongestVarRefChain == null ? new ArrayDeque<String>()
: inoutLongestVarRefChain;
final Expression<?> varExpr = getInstance(varDef.getExpression().getValue(), xPathCompiler, longestVarRefChain);
final BaseVariableReference<?> var = new BaseVariableReference<>(varId, varExpr, longestVarRefChain);
return idToVariableMap.put(varId, var);
......@@ -165,42 +205,56 @@ public class ExpressionFactoryImpl implements ExpressionFactory
/** {@inheritDoc} */
@Override
public VariableReference<?> removeVariable(String varId)
{
public VariableReference<?> removeVariable(String varId) {
return idToVariableMap.remove(varId);
}
/**
* Resolves a VariableReference to the corresponding VariableReference(Definition) and validates the depth of VariableReference, i.e. the length of VariableReference chain. A chain of variable
* references is a list of VariableIds, such that V1 -> V2 ->... -> Vn, where 'V1 -> V2' means: V1's Expression contains a VariableReference to V2.
* Resolves a VariableReference to the corresponding
* VariableReference(Definition) and validates the depth of
* VariableReference, i.e. the length of VariableReference chain. A chain of
* variable references is a list of VariableIds, such that V1 -> V2 ->... ->
* Vn, where 'V1 -> V2' means: V1's Expression contains a VariableReference
* to V2.
*
* @param jaxbVarRef
* the JAXB/XACML VariableReference with merely identifying a VariableDefinition by its VariableId
* the JAXB/XACML VariableReference with merely identifying a
* VariableDefinition by its VariableId
*
* @return VariableReference containing the resolved VariableDefinition's expression referenced by <code>jaxbVarRef</code> as known by this factory, or null if unknown
* @return VariableReference containing the resolved VariableDefinition's
* expression referenced by <code>jaxbVarRef</code> as known by this
* factory, or null if unknown
* @param longestVarRefChain
* If we are resolving a VariableReference in a VariableDefinition's expression (may be null if not), this is the longest chain of VariableReferences starting from a one in this
* VariableDefinition. If we are not resolving a VariableReference in a VariableDefinition's expression, this may be null.This is used to detect exceeding reference depth (see
* {@link #ExpressionFactoryImpl(int)} for the limit. In a Expression such as an Apply, we can have multiple VariableReferences referencing different VariableDefinitions. So we can have
* different depths of VariableReference references. We compare the length of the current longest chain with the one we would get by adding the longest one in the referenced
* VariableDefinition and <code>jaxbVarRef</code>'s VariableId. If the latter is longer, its content becomes the content <code>longestVarRefChain</code>.
* If we are resolving a VariableReference in a
* VariableDefinition's expression (may be null if not), this is
* the longest chain of VariableReferences starting from a one in
* this VariableDefinition. If we are not resolving a
* VariableReference in a VariableDefinition's expression, this
* may be null.This is used to detect exceeding reference depth
* (see {@link #ExpressionFactoryImpl(int)} for the limit. In a
* Expression such as an Apply, we can have multiple
* VariableReferences referencing different VariableDefinitions.
* So we can have different depths of VariableReference
* references. We compare the length of the current longest chain
* with the one we would get by adding the longest one in the
* referenced VariableDefinition and <code>jaxbVarRef</code>'s
* VariableId. If the latter is longer, its content becomes the
* content <code>longestVarRefChain</code>.
* @throws UnknownIdentifierException
* if VariableReference's VariableId is unknown by this factory
*/
private BaseVariableReference<?> getVariable(VariableReferenceType jaxbVarRef, Deque<String> longestVarRefChain) throws IllegalArgumentException
{
private BaseVariableReference<?> getVariable(VariableReferenceType jaxbVarRef, Deque<String> longestVarRefChain)
throws IllegalArgumentException {
final String varId = jaxbVarRef.getVariableId();
final BaseVariableReference<?> var = idToVariableMap.get(varId);
if (var == null)
{
throw new IllegalArgumentException("VariableReference's VariableId=" + varId + " unknown in the current context, i.e. does not match any prior VariableDefinition's VariableId");
if (var == null) {
throw new IllegalArgumentException("VariableReference's VariableId=" + varId
+ " unknown in the current context, i.e. does not match any prior VariableDefinition's VariableId");
}
if (longestVarRefChain != null)
{
if (longestVarRefChain != null) {
final Deque<String> referencedVarLongestRefChain = var.getLongestVariableReferenceChain();
if (referencedVarLongestRefChain.size() + 1 > longestVarRefChain.size())
{
if (referencedVarLongestRefChain.size() + 1 > longestVarRefChain.size()) {
// current longest is no longer the longest, so replace with new
// longest's content
longestVarRefChain.clear();
......@@ -208,9 +262,10 @@ public class ExpressionFactoryImpl implements ExpressionFactory
longestVarRefChain.addAll(referencedVarLongestRefChain);
}
if (maxVariableReferenceDepth != UNLIMITED_MAX_VARIABLE_REF_DEPTH && longestVarRefChain.size() > this.maxVariableReferenceDepth)
{
throw new IllegalArgumentException("Max allowed VariableReference depth (" + this.maxVariableReferenceDepth + ") exceeded by length (" + longestVarRefChain.size()
if (maxVariableReferenceDepth != UNLIMITED_MAX_VARIABLE_REF_DEPTH
&& longestVarRefChain.size() > this.maxVariableReferenceDepth) {
throw new IllegalArgumentException("Max allowed VariableReference depth ("
+ this.maxVariableReferenceDepth + ") exceeded by length (" + longestVarRefChain.size()
+ ") of VariableReference Reference chain: " + longestVarRefChain);
}
......@@ -222,31 +277,36 @@ public class ExpressionFactoryImpl implements ExpressionFactory
/**
* {@inheritDoc}
*
* Create a function instance using the function registry passed as parameter to {@link #ExpressionFactoryImpl(DatatypeFactoryRegistry, FunctionRegistry, List, int, boolean, boolean)} .
* Create a function instance using the function registry passed as
* parameter to
* {@link #ExpressionFactoryImpl(DatatypeFactoryRegistry, FunctionRegistry, List, int, boolean, boolean)}
* .
*/
@Override
public Function<?> getFunction(String functionId)
{
public Function<?> getFunction(String functionId) {
return this.functionRegistry.getFunction(functionId);
}
/**
* {@inheritDoc}
*
* Create a function instance using the function registry passed as parameter to {@link #ExpressionFactoryImpl(DatatypeFactoryRegistry, FunctionRegistry, List, int, boolean, boolean)} .
* Create a function instance using the function registry passed as
* parameter to
* {@link #ExpressionFactoryImpl(DatatypeFactoryRegistry, FunctionRegistry, List, int, boolean, boolean)}
* .
*/
@Override
public Function<?> getFunction(String functionId, Datatype<?> subFunctionReturnType) throws IllegalArgumentException
{
if (subFunctionReturnType == null)
{
public Function<?> getFunction(String functionId, Datatype<?> subFunctionReturnType)
throws IllegalArgumentException {
if (subFunctionReturnType == null) {
return getFunction(functionId);
}
final DatatypeFactory<?> subFuncReturnTypeFactory = this.datatypeFactoryRegistry.getExtension(subFunctionReturnType.getId());
if (subFuncReturnTypeFactory == null)
{
throw new IllegalArgumentException("Invalid sub-function's return type specified: unknown/unsupported ID: " + subFunctionReturnType.getId());
final DatatypeFactory<?> subFuncReturnTypeFactory = this.datatypeFactoryRegistry
.getExtension(subFunctionReturnType.getId());
if (subFuncReturnTypeFactory == null) {
throw new IllegalArgumentException("Invalid sub-function's return type specified: unknown/unsupported ID: "
+ subFunctionReturnType.getId());
}
return this.functionRegistry.getFunction(functionId, subFuncReturnTypeFactory);
......@@ -255,94 +315,86 @@ public class ExpressionFactoryImpl implements ExpressionFactory
/*
* (non-Javadoc)
*
* @see com.thalesgroup.authzforce.core.eval.ExpressionFactory#getInstance(oasis. names.tc.xacml._3_0 .core.schema.wd_17.ExpressionType, oasis.names.tc.xacml._3_0.core.schema.wd_17.DefaultsType,
* java.util.List)
* @see
* com.thalesgroup.authzforce.core.eval.ExpressionFactory#getInstance(oasis.
* names.tc.xacml._3_0 .core.schema.wd_17.ExpressionType,
* oasis.names.tc.xacml._3_0.core.schema.wd_17.DefaultsType, java.util.List)
*/
/** {@inheritDoc} */
@Override
public Expression<?> getInstance(ExpressionType expr, XPathCompiler xPathCompiler, Deque<String> longestVarRefChain) throws IllegalArgumentException
{
public Expression<?> getInstance(ExpressionType expr, XPathCompiler xPathCompiler, Deque<String> longestVarRefChain)
throws IllegalArgumentException {
final Expression<?> expression;
/*
* We check all types of Expression: <Apply>, <AttributeSelector>, <AttributeValue>, <Function>, <VariableReference> and <AttributeDesignator>
* We check all types of Expression: <Apply>, <AttributeSelector>,
* <AttributeValue>, <Function>, <VariableReference> and
* <AttributeDesignator>
*/
if (expr instanceof ApplyType)
{
if (expr instanceof ApplyType) {
expression = Apply.getInstance((ApplyType) expr, xPathCompiler, this, longestVarRefChain);
} else if (expr instanceof AttributeDesignatorType)
{
if (this.attributeProvider == null)
{
} else if (expr instanceof AttributeDesignatorType) {
if (this.attributeProvider == null) {
throw UNSUPPORTED_ATTRIBUTE_DESIGNATOR_OR_SELECTOR_BECAUSE_OF_NULL_ATTRIBUTE_PROVIDER_EXCEPTION;
}
final AttributeDesignatorType jaxbAttrDes = (AttributeDesignatorType) expr;
if (this.issuerRequiredOnAttributeDesignators && jaxbAttrDes.getIssuer() == null)
{
if (this.issuerRequiredOnAttributeDesignators && jaxbAttrDes.getIssuer() == null) {
throw MISSING_ATTRIBUTE_DESIGNATOR_ISSUER_EXCEPTION;
}
final DatatypeFactory<?> attrFactory = datatypeFactoryRegistry.getExtension(jaxbAttrDes.getDataType());
if (attrFactory == null)
{
throw new IllegalArgumentException("Unsupported Datatype used in AttributeDesignator: " + jaxbAttrDes.getDataType());
if (attrFactory == null) {
throw new IllegalArgumentException(
"Unsupported Datatype used in AttributeDesignator: " + jaxbAttrDes.getDataType());
}
expression = new AttributeDesignator<>(jaxbAttrDes, attrFactory.getBagDatatype(), attributeProvider);
} else if (expr instanceof AttributeSelectorType)
{
if (!allowAttributeSelectors)
{
} else if (expr instanceof AttributeSelectorType) {