Commit 67717a3c authored by cdanger's avatar cdanger

- Fixed issue #21 (OW2) with non-regression test

- Fixed issue #22 (OW2) with non-regression test
- New feature to set Standard Current Time Environment Attribute
(PDP_ONLY, REQUEST_ELSE_PDP, REQUEST_ONLY) with unit tests
- New features: strictAttributeIssuerMatch=false supported when
retrieving attributes from provider modules (if attribute has Issuer,
Issuer-less copy added to context)
- New way of handling ReturnPolicyIdList (return applicable policies)
with new definition of applicable policies (not returning NotApplicable
and enclosing policy is applicable, if any)
-> changes to response in tests IIIG301,302
- Removed TestApplyMarshalling because we consider no longer the
responsibility of the PDP to be able to marshall XACML instances, but
the caller; in particular classes ApplyExpression,
AttributeDesignatorExpression, AttributeSelectorExpression,
AttributeAssigmnentExpressionEvaluator no longer extending JAXB classes
to simplify and improve code memory usage
- New  utility class StandardCombiningAlgorithms for registry of
standard combining algorithms
- New  utility class StandardEnvironmentAttributes for registry of
standard environment attributes
- - New  utility class StandardFunctions for registry of standard
functions
- Fixed issues with autoboxing/unboxing
- Use of Guava Preconditions.checkNotNull() and ImmutableList
- Use of koloboke HashMap/HashSet
- Removed MutableDecisionResult
parent 3581dcf0
......@@ -70,8 +70,8 @@
<configuration>
<verbose>true</verbose>
<excludeRoots>
<excludeRoot>target/generated-sources</excludeRoot>
<excludeRoot>target/generated-test-sources</excludeRoot>
<excludeRoot>target/generated-sources/xjc</excludeRoot>
<excludeRoot>target/generated-test-sources/xjc</excludeRoot>
</excludeRoots>
</configuration>
<executions>
......
......@@ -24,13 +24,14 @@
package com.sun.xacml;
/**
* Exception that gets thrown if an unknown identifier was used, such as the identifier used in any of the standard factories.
* Exception that gets thrown if an unknown identifier was used, such as the identifier used in any of the standard
* factories.
*
* @since 1.0
* @author Seth Proctor
* @version $Id: $
*/
public class UnknownIdentifierException extends Exception
public final class UnknownIdentifierException extends Exception
{
/**
......
......@@ -21,26 +21,26 @@ package org.ow2.authzforce.core.pdp.impl;
import java.util.ArrayList;
import java.util.List;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOf;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Match;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.expression.ExpressionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Match;
/**
* XACML AllOf evaluator
*
* @version $Id: $
*/
public class AllOfEvaluator
public final class AllOfEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(AllOfEvaluator.class);
private static final IllegalArgumentException NO_MATCH_EXCEPTION = new IllegalArgumentException("<AllOf> empty. Must contain at least one <Match>");
private static final IllegalArgumentException NO_MATCH_EXCEPTION = new IllegalArgumentException(
"<AllOf> empty. Must contain at least one <Match>");
// Store the list of Matches as evaluatable Match types to avoid casting from JAXB MatchType
// during evaluation
......@@ -49,8 +49,8 @@ public class AllOfEvaluator
/**
* Instantiates AllOf (evaluator) from XACML-Schema-derived <code>AllOf</code>.
*
* @param jaxbAllOf
* XACML-schema-derived JAXB AllOf
* @param jaxbMatches
* XACML-schema-derived JAXB Match elements
* @param xPathCompiler
* XPath compiler corresponding to enclosing policy(set) default XPath version
* @param expFactory
......@@ -58,10 +58,10 @@ public class AllOfEvaluator
* @throws java.lang.IllegalArgumentException
* one of the child Match elements is invalid
*/
public AllOfEvaluator(AllOf jaxbAllOf, XPathCompiler xPathCompiler, ExpressionFactory expFactory) throws IllegalArgumentException
public AllOfEvaluator(List<Match> jaxbMatches, XPathCompiler xPathCompiler, ExpressionFactory expFactory)
throws IllegalArgumentException
{
final List<Match> jaxbMatches = jaxbAllOf.getMatches();
if (jaxbMatches.isEmpty())
if (jaxbMatches == null || jaxbMatches.isEmpty())
{
throw NO_MATCH_EXCEPTION;
}
......@@ -74,7 +74,8 @@ public class AllOfEvaluator
try
{
matchEvaluator = new MatchEvaluator(jaxbMatch, xPathCompiler, expFactory);
} catch (IllegalArgumentException e)
}
catch (IllegalArgumentException e)
{
throw new IllegalArgumentException("Invalid <AllOf>'s <Match>#" + matchIndex, e);
}
......@@ -85,7 +86,8 @@ public class AllOfEvaluator
}
/**
* Determines whether this <code>AllOf</code> matches the input request (whether it is applicable).Here is the table shown in the specification: <code>
* Determines whether this <code>AllOf</code> matches the input request (whether it is applicable).Here is the table
* shown in the specification: <code>
* <Match> values <AllOf> value
* All True “Match�?
* No False and at least
......@@ -119,10 +121,19 @@ public class AllOfEvaluator
try
{
isMatched = matchEvaluator.match(context);
LOGGER.debug("AllOf/Match#{} -> {}", childIndex, isMatched);
} catch (IndeterminateEvaluationException e)
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Boolean.valueOf(...), Integer.valueOf(...)
LOGGER.debug("AllOf/Match#{} -> {}", childIndex, isMatched);
}
}
catch (IndeterminateEvaluationException e)
{
LOGGER.debug("AllOf/Match#{} -> Indeterminate", childIndex, e);
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Integer.valueOf(...)
LOGGER.debug("AllOf/Match#{} -> Indeterminate", childIndex, e);
}
lastIndeterminate = e;
lastIndeterminateChildIndex = childIndex;
continue;
......@@ -149,6 +160,7 @@ public class AllOfEvaluator
}
// No False but at least one Indeterminate (lastIndeterminate != null)
throw new IndeterminateEvaluationException("Error evaluating <AllOf>'s <Match>#" + lastIndeterminateChildIndex, lastIndeterminate.getStatusCode(), lastIndeterminate);
throw new IndeterminateEvaluationException("Error evaluating <AllOf>'s <Match>#" + lastIndeterminateChildIndex,
lastIndeterminate.getStatusCode(), lastIndeterminate);
}
}
......@@ -24,26 +24,26 @@ package org.ow2.authzforce.core.pdp.impl;
import java.util.ArrayList;
import java.util.List;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOf;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AnyOf;
import org.ow2.authzforce.core.pdp.api.EvaluationContext;
import org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException;
import org.ow2.authzforce.core.pdp.api.expression.ExpressionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.saxon.s9api.XPathCompiler;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AllOf;
/**
* AnyOf evaluator
*
* @version $Id: $
*/
public class AnyOfEvaluator
public final class AnyOfEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(AnyOfEvaluator.class);
private static final IllegalArgumentException NO_ALL_OF_EXCEPTION = new IllegalArgumentException("<AnyOf> empty. Must contain at least one <AllOf>");
private static final IllegalArgumentException NO_ALL_OF_EXCEPTION = new IllegalArgumentException(
"<AnyOf> empty. Must contain at least one <AllOf>");
// Store the list of AllOf as evaluatable AllOf types to avoid casting from JAXB AllOfType
// during evaluation
......@@ -52,8 +52,8 @@ public class AnyOfEvaluator
/**
* Constructor that creates a new <code>AnyOf</code> evaluator based on the given XACML-schema-derived JAXB AnyOf.
*
* @param jaxbAnyOf
* JAXB AnyOf
* @param jaxbAllOfList
* JAXB AllOf elements
* @param xPathCompiler
* XPath compiler corresponding to enclosing policy(set) default XPath version
* @param expFactory
......@@ -61,10 +61,10 @@ public class AnyOfEvaluator
* @throws java.lang.IllegalArgumentException
* if one of the child AllOf elements is invalid
*/
public AnyOfEvaluator(AnyOf jaxbAnyOf, XPathCompiler xPathCompiler, ExpressionFactory expFactory) throws IllegalArgumentException
public AnyOfEvaluator(List<AllOf> jaxbAllOfList, XPathCompiler xPathCompiler, ExpressionFactory expFactory)
throws IllegalArgumentException
{
final List<AllOf> jaxbAllOfList = jaxbAnyOf.getAllOves();
if (jaxbAllOfList.isEmpty())
if (jaxbAllOfList == null || jaxbAllOfList.isEmpty())
{
throw NO_ALL_OF_EXCEPTION;
}
......@@ -76,8 +76,9 @@ public class AnyOfEvaluator
final AllOfEvaluator allOfEvaluator;
try
{
allOfEvaluator = new AllOfEvaluator(jaxbAllOf, xPathCompiler, expFactory);
} catch (IllegalArgumentException e)
allOfEvaluator = new AllOfEvaluator(jaxbAllOf.getMatches(), xPathCompiler, expFactory);
}
catch (IllegalArgumentException e)
{
throw new IllegalArgumentException("Invalid <AnyOf>'s <AllOf>#" + matchIndex, e);
}
......@@ -88,8 +89,9 @@ public class AnyOfEvaluator
}
/**
* Determines whether this <code>AnyOf</code> matches the input request (whether it is applicable). If all the AllOf values is No_Match so it's a No_Match. If all matches it's a Match. If None
* matches and at least one “Indeterminate�? it's Indeterminate
* Determines whether this <code>AnyOf</code> matches the input request (whether it is applicable). If all the AllOf
* values is No_Match so it's a No_Match. If all matches it's a Match. If None matches and at least one
* “Indeterminate�? it's Indeterminate
*
* <pre>
* AllOf values AnyOf value
......@@ -125,10 +127,19 @@ public class AnyOfEvaluator
try
{
isMatched = allOfEvaluator.match(context);
LOGGER.debug("AnyOf/AllOf#{} -> {}", childIndex, isMatched);
} catch (IndeterminateEvaluationException e)
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Boolean.valueOf(...), Integer.valueOf(...)
LOGGER.debug("AnyOf/AllOf#{} -> {}", childIndex, isMatched);
}
}
catch (IndeterminateEvaluationException e)
{
LOGGER.debug("AnyOf/AllOf#{} -> Indeterminate", childIndex, e);
if (LOGGER.isDebugEnabled())
{
// Beware of autoboxing which causes call to Integer.valueOf(...)
LOGGER.debug("AnyOf/AllOf#{} -> Indeterminate", childIndex, e);
}
lastIndeterminate = e;
lastIndeterminateChildIndex = childIndex;
continue;
......@@ -155,7 +166,8 @@ public class AnyOfEvaluator
}
// No Match and at least one Indeterminate (lastIndeterminate != null) -> Indeterminate
throw new IndeterminateEvaluationException("Error evaluating <AnyOf>'s <AllOf>#" + lastIndeterminateChildIndex, lastIndeterminate.getStatusCode(), lastIndeterminate);
throw new IndeterminateEvaluationException("Error evaluating <AnyOf>'s <AllOf>#" + lastIndeterminateChildIndex,
lastIndeterminate.getStatusCode(), lastIndeterminate);
}
}
......@@ -22,15 +22,9 @@
package org.ow2.authzforce.core.pdp.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.xml.bind.JAXBElement;
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 oasis.names.tc.xacml._3_0.core.schema.wd_17.ExpressionType;
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;
......@@ -41,45 +35,34 @@ import org.ow2.authzforce.core.pdp.api.value.Value;
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.AttributeAssignment;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression;
/**
* XACML AttributeAssignmentExpression evaluator
*
* @version $Id: $
*/
public class AttributeAssignmentExpressionEvaluator extends AttributeAssignmentExpression
public final class AttributeAssignmentExpressionEvaluator
{
private static final Logger LOGGER = LoggerFactory.getLogger(AttributeAssignmentExpressionEvaluator.class);
private final transient Expression<?> evaluatableExpression;
private final Expression<?> evaluatableExpression;
private static final UnsupportedOperationException UNSUPPORTED_SET_EXPRESSION_OPERATION_EXCEPTION = new UnsupportedOperationException("Unsupported operation: 'Expression' attribute is read-only");
private final String attributeId;
/*
* (non-Javadoc)
*
* @see oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression#getExpression()
*/
/** {@inheritDoc} */
@Override
public final JAXBElement<? extends ExpressionType> getExpression()
{
return evaluatableExpression.getJAXBElement();
}
private final String category;
/*
* (non-Javadoc)
*
* @see oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression#setExpression(javax .xml.bind.JAXBElement)
*/
/** {@inheritDoc} */
@Override
public final void setExpression(JAXBElement<? extends ExpressionType> value)
{
throw UNSUPPORTED_SET_EXPRESSION_OPERATION_EXCEPTION;
}
private final String issuer;
private transient volatile String toString = null; // Effective Java - Item 71
/**
* Instantiates evaluatable AttributeAssignment expression from XACML-Schema-derived JAXB {@link oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression}
* Instantiates evaluatable AttributeAssignment expression evaluator from XACML-Schema-derived JAXB
* {@link oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpression}
*
* @param jaxbAttrAssignExp
* XACML-schema-derived JAXB AttributeAssignmentExpression
......@@ -90,25 +73,33 @@ public class AttributeAssignmentExpressionEvaluator extends AttributeAssignmentE
* @throws java.lang.IllegalArgumentException
* invalid AttributeAssignmentExpression's Expression
*/
public AttributeAssignmentExpressionEvaluator(AttributeAssignmentExpression jaxbAttrAssignExp, XPathCompiler xPathCompiler, ExpressionFactory expFactory) throws IllegalArgumentException
public AttributeAssignmentExpressionEvaluator(final AttributeAssignmentExpression jaxbAttrAssignExp,
final XPathCompiler xPathCompiler, final ExpressionFactory expFactory) throws IllegalArgumentException
{
// JAXB fields
this.attributeId = jaxbAttrAssignExp.getAttributeId();
this.category = jaxbAttrAssignExp.getCategory();
this.issuer = jaxbAttrAssignExp.getIssuer();
/*
* Set JAXB field to null, getExpression() overridden and setExpression() not allowed instead
* Cannot used AttributeGUID class to handle metadata because AttributeAssignment Category is not required like
* in AttributeDesignator which is what the AttributeGUID is used for
*/
this.expression = null;
// END OF JAXB fields
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.evaluatableExpression = expFactory.getInstance(jaxbAttrAssignExp.getExpression().getValue(), xPathCompiler, null);
private AttributeAssignment newAttributeAssignment(final AttributeValue attrVal)
{
return new AttributeAssignment(attrVal.getContent(), attrVal.getDataType(), attrVal.getOtherAttributes(),
this.attributeId, this.category, this.issuer);
}
/**
* Evaluates to AttributeAssignments Section 5.39 and 5.40 of XACML 3.0 core spec: If an AttributeAssignmentExpression evaluates to an atomic attribute value, then there MUST be one resulting
* AttributeAssignment which MUST contain this single attribute value. If the AttributeAssignmentExpression evaluates to a bag, then there MUST be a resulting AttributeAssignment for each of the
* values in the bag. If the bag is empty, there shall be no AttributeAssignment from this AttributeAssignmentExpression
* Evaluates to AttributeAssignments Section 5.39 and 5.40 of XACML 3.0 core spec: If an
* AttributeAssignmentExpression evaluates to an atomic attribute value, then there MUST be one resulting
* AttributeAssignment which MUST contain this single attribute value. If the AttributeAssignmentExpression
* evaluates to a bag, then there MUST be a resulting AttributeAssignment for each of the values in the bag. If the
* bag is empty, there shall be no AttributeAssignment from this AttributeAssignmentExpression
*
* @param context
* evaluation context
......@@ -116,42 +107,54 @@ public class AttributeAssignmentExpressionEvaluator extends AttributeAssignmentE
* @throws org.ow2.authzforce.core.pdp.api.IndeterminateEvaluationException
* if evaluation of the Expression in this context fails (Indeterminate)
*/
public List<AttributeAssignment> evaluate(EvaluationContext context) throws IndeterminateEvaluationException
public List<AttributeAssignment> evaluate(final EvaluationContext context) throws IndeterminateEvaluationException
{
final Value result = this.evaluatableExpression.evaluate(context);
LOGGER.debug("AttributeAssignmentExpression[Category={},Issuer={},Id={}]/Expression -> {}", this.category, this.issuer, this.attributeId, result);
LOGGER.debug("{}/Expression -> {}", this, result);
final List<AttributeAssignment> attrAssignList = new ArrayList<>();
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:
* 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 AttributeValue attrVal : bag)
{
final AttributeAssignment attrAssignment = new AttributeAssignment(attrVal.getContent(), attrVal.getDataType(), attrVal.getOtherAttributes(), this.attributeId, this.category,
this.issuer);
attrAssignList.add(attrAssignment);
attrAssignList.add(newAttributeAssignment(attrVal));
}
} else
}
else
{
// atomic (see spec §5.30, 5.40) / primitive attribute value
final AttributeValue attrVal = (AttributeValue) result;
final AttributeAssignment attrAssignment = new AttributeAssignment(attrVal.getContent(), attrVal.getDataType(), attrVal.getOtherAttributes(), this.attributeId, this.category, this.issuer);
attrAssignList.add(attrAssignment);
attrAssignList = Collections.singletonList(newAttributeAssignment((AttributeValue) result));
}
return attrAssignList;
}
@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
// 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",
// final AttributeAssignment attrAssignment = new AttributeAssignment(Collections.<Serializable>
// singletonList("1.0"), "mytype", null, "myattribute1",
// "mycategory", null);
//
// Marshaller marshaller = XACMLBindingUtils.createXacml3Marshaller();
......
......@@ -18,135 +18,92 @@
*/
package org.ow2.authzforce.core.pdp.impl;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.ow2.authzforce.core.pdp.api.PdpExtension;
import org.ow2.authzforce.core.pdp.api.PdpExtensionRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.koloboke.collect.map.ObjObjMap;
import com.koloboke.collect.map.hash.HashObjObjMaps;
import com.koloboke.collect.set.hash.HashObjSets;
/**
* This is an implementation of <code>PdpExtensionRegistry</code>.
* This is a base implementation of <code>PdpExtensionRegistry</code>. This should be used as basis to implement (in a
* final class) an immutable PDP extension registry of a specific type. If you need a generic immutable PDP extension
* registry, see {
*
* @param <T>
* type of extension in this registry
* @version $Id: $
*/
public class BasePdpExtensionRegistry<T extends PdpExtension> implements PdpExtensionRegistry<T>
public abstract class BasePdpExtensionRegistry<T extends PdpExtension> implements PdpExtensionRegistry<T>
{
private static final Logger LOGGER = LoggerFactory.getLogger(BasePdpExtensionRegistry.class);
private static final IllegalArgumentException NULL_EXTENSION_CLASS_EXCEPTION = new IllegalArgumentException("Extension class arg undefined");
private static final IllegalArgumentException NULL_EXTENSIONS_EXCEPTION = new IllegalArgumentException("ExtensionsById arg undefined");
private final Class<? super T> extClass;
// the backing maps for the Function objects
private final Map<String, T> extensionsById;
private final transient String toString;
/**
* Instantiates registry from a map (id -> extension)
*
* Instantiates immutable registry from a map.
*
* @param extensionClass
* extension class
*
* @param extensionsById
* extensions indexed by ID
* @param extensions
* extensions input map; the registry actually creates and uses an immutable copy of this map internally
* to avoid external modifications on the internal map
*/
private BasePdpExtensionRegistry(Class<? super T> extensionClass, Map<String, T> extensionsById)
protected BasePdpExtensionRegistry(Class<? super T> extensionClass, Map<String, T> extensionsById)
{
if (extensionClass == null)
{
throw NULL_EXTENSION_CLASS_EXCEPTION;
}
if (extensionsById == null)
{
throw NULL_EXTENSIONS_EXCEPTION;
}
assert extensionClass != null && extensionsById != null;
this.extClass = extensionClass;
this.extensionsById = extensionsById;
this.extensionsById = HashObjObjMaps.newImmutableMap(extensionsById);
this.toString = this + "( extensionClass= " + extClass.getCanonicalName() + " )";
}
/**
* Instantiates immutable registry from a set of extensions
*
* @param extensionClass
* extension class
* @param extensions
* extensions
*/
public BasePdpExtensionRegistry(Class<? super T> extensionClass, Set<T> extensions)
/** {@inheritDoc} */
@Override
public final T getExtension(String identity)
{
if (extensionClass == null)
{
throw NULL_EXTENSION_CLASS_EXCEPTION;
}
if (extensions == null)
{
throw NULL_EXTENSIONS_EXCEPTION;
}
return extensionsById.get(identity);
}
this.extClass = extensionClass;
/** {@inheritDoc} */
@Override
public final Set<T> getExtensions()
{
return HashObjSets.newImmutableSet(extensionsById.values());
}
this.extensionsById = new HashMap<>();
for (final T extension : extensions)
private static <E extends PdpExtension> Map<String, E> newImmutableMap(Set<E> extensions)
{
final ObjObjMap<String, E> mutableMap = HashObjObjMaps.newUpdatableMap(extensions.size());
for (final E extension : extensions)
{
final String id = extension.getId();
this.extensionsById.put(id, extension);
mutableMap.put(extension.getId(), extension);
}
}
/**
* Default constructor. No superset factory is used.
*
* @param extensionClass
* extension class
*/
public BasePdpExtensionRegistry(Class<? super T> extensionClass)
{
this(extensionClass, new HashMap<String, T>());
return HashObjObjMaps.newImmutableMap(mutableMap);
}
/**
* Constructor that sets a "base registry" from which this inherits all the extensions. Used for instance to build a new registry based on a standard one like the StandardFunctionRegistry for
* standard functions).
* Instantiates immutable registry from a set of extensions
*
* @param baseRegistry
* the base/parent registry on which this one is based or null
* @param extensionClass
* extension class
* extension class (required not null)
* @param extensions
* extensions (required not null)
*/
public BasePdpExtensionRegistry(Class<? super T> extensionClass, BasePdpExtensionRegistry<T> baseRegistry)
protected BasePdpExtensionRegistry(Class<? super T> extensionClass, Set<T> extensions)
{
this(extensionClass, baseRegistry == null ? new HashMap<String, T>() : new HashMap<>(baseRegistry.extensionsById));
this(extensionClass, newImmutableMap(extensions));
}
/** {@inheritDoc} */
@Override
public void addExtension(T extension) throws IllegalArgumentException
public String toString()
{
final String id = extension.getId();
// make sure nothing already registered with same ID
if (extensionsById.containsKey(id))
{
throw new IllegalArgumentException("Conflict: extension (id=" + id + ") already registered");
}
extensionsById.put(id, extension);
LOGGER.debug("Added PDP extension of {} to registry: {}", extClass, extension);
}
/** {@inheritDoc} */
@Override
public T getExtension(String identity)
{
return extensionsById.get(identity);
return toString;
}
}
/**
* Copyright (C) 2012-2016 Thales Services SAS.
*
* This file is part of AuthZForce CE.
*
* AuthZForce CE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AuthZForce CE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AuthZForce CE. If not, see <http://www.gnu.org/licenses/>.
*/