Commit 49b36532 authored by Cyril Dangerville's avatar Cyril Dangerville

- Added PDP XML schema for loading PDP configuration using JAXB only

(not DOM) -> PdpConfigurationManager
- Fixed NPE in permit-unless-deny/deny-unless-permit algs
- Fixed deny-unless-permit/deny-unless-permit algs to combine
obligations/advice from combined elements (not only the one that
returned permit for denyUnlessPermit, or deny for permitUnlessDeny, but
also others)
- Removed commented classes/dead code/code not used anymore
- Added framework for handling PDP extension: IPdpExtension interface
and use it as interface for all PDP extensions starting with
AttributeFinderModule, PolicyFinderModule with corresponding XML type
(module/extension configuration model) as type parameter;
PdpExtensionFactory, PdpModelHandler, SchemaHandler
- Changed parent project version to last SNAPSHOT
- Add gpl license for src/main/java/com/thalesgroup/authzforce/core
- Updated Thales Apache license
- Added PdpBean to use PDP as JNDI resource
- moved license files out of src/ folder to distinguish from source code
- Removed thales author names from comment (control version system, e.g.
git, is more reliable)
- Added PdpModelHandler to handle PDP configuration model with support
of dynamic extension loading (attribute finders, policy finders, etc.)
- Added PdpConfigurationManager does the job of ConfigurationStore but
using JAXB and new PDP Configuration XML schema instead of DOM, meant to
replace ConfigurationStore completely
- Replaced use of custom com.sun.xacml.CacheManager with Ehcache cache
API
- Migrated code to java7 style
parent f86c6581
Copyright (C) ${h_inceptionYear}-${h_currentYear} ${h_copyrightOwner} - All rights reserved.
Copyright (C) ${inceptionYear}-${currentYear} ${copyrightOwner} - All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......
Copyright (C) ${inceptionYear}-${currentYear} ${copyrightOwner}.
This file is part of ${projectName}.
${projectName} 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.
${projectName} 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 ${projectName}. If not, see <http://www.gnu.org/licenses/>.
This diff is collapsed.
This diff is collapsed.
......@@ -66,7 +66,8 @@ import com.sun.xacml.attr.xacmlv3.AttributeDesignator;
import com.sun.xacml.attr.xacmlv3.AttributeValue;
import com.sun.xacml.cond.xacmlv3.EvaluationResult;
import com.sun.xacml.finder.AttributeFinder;
import com.thalesgroup.authzforce.BindingUtility;
import com.thalesgroup.appsec.util.Utils;
import com.thalesgroup.authzforce.core.PdpModelHandler;
import com.thalesgroup.authzforce.xacml.schema.XACMLCategory;
/**
......@@ -835,40 +836,51 @@ public class BasicEvaluationCtx implements EvaluationCtx
}
/**
* Helper function for the resource, action and environment methods to get an attribute.
* Helper function for the resource, action and environment methods to get an attribute. The
* input map is updated with the new attribute corresponding to input (id,type,issuer) if it was
* not already in the map
*/
private EvaluationResult getGenericAttributes(URI type, URI id, URI issuer, Map<String, Set<Attribute>> map, URI category, int designatorType)
{
/**
* Requirement #1: When the attribute finder is called via callHelper(), the result must be
* saved in the evaluation context to guarantee the same result/value next time it is used
* in the same context. At least 3 reasons: 1. Performance optimization: calling attribute
* finder costs more than getting it from the context attribute map. 2. ACCOUNTING/AUDIT: if
* you call the attribute finder more than once for the same attribute, you may have value
* changes from a call to another. If you log attribute values for accounting/audit reasons,
* which value do you log? This is critical to have the correct information in order to
* understand/investigate a posteriori why a given access was permitted/denied. 3. Policy
* decision consistency: this is pretty close to the previous reason, expressed in more
* generic terms. If the value of a given attribute changed from one attribute finding to
* another when it is used/required more than once in the same decision request context, the
* PDP ends up evaluating different parts of the <PolicySet> based on different values of
* the same attribute, again, for the same decision request. And the longer the evaluation
* takes time to process, the more changes can occur, and the more inconsistent the
* evaluation will be.
* in the same context. At least 3 reasons:
*
* 1. Performance optimization: calling attribute finder costs more than getting it from the
* context attribute map.
*
* 2. ACCOUNTING/AUDIT: if you call the attribute finder more than once for the same
* attribute, you may have value changes from a call to another. If you log attribute values
* for accounting/audit reasons, which value do you log? This is critical to have the
* correct information in order to understand/investigate a posteriori why a given access
* was permitted/denied.
*
* 3. Policy decision consistency: this is pretty close to the previous reason, expressed in
* more generic terms. If the value of a given attribute changed from one attribute finding
* to another when it is used/required more than once in the same decision request context,
* the PDP ends up evaluating different parts of the <PolicySet> based on different values
* of the same attribute, again, for the same decision request. And the longer the
* evaluation takes time to process, the more changes can occur, and the more inconsistent
* the evaluation will be.
*/
// try to find the id
final String idStr = id.toString();
final String issuerStr = (issuer == null) ? null : issuer.toString();
final String typeStr = type.toString();
/*
* Check if some attributes already (found) in current evaluation context for attribute 'id'
* arg
* Check if some attributes already (found) in current evaluation context (map) for
* attribute 'id' arg
*/
final Set<Attribute> attrSet = map.get(idStr);
final Set<Attribute> oldAttrSet = map.get(idStr);
final List<AttributeValue> attributeValues;
// Map to be updated with new attributes resulting from call to AttributeFinder
/*
* newAttrSet will contain the existing attribute values if any in the current map (eval
* context), or the new attributes resulting from callHelper() (call to AttributeFinder) if
* no attribute found for input (id,type,issuer) in the map yet
*/
final Set<Attribute> newAttrSet;
if (attrSet == null)
if (oldAttrSet == null)
{
// the request didn't have an attribute with that id, so no attribute values yet
attributeValues = new ArrayList<>();
......@@ -883,16 +895,13 @@ public class BasicEvaluationCtx implements EvaluationCtx
*/
try
{
/*
* FIXME: We need to use the getContent() method to retrieve attributeValues
*/
attributeValues = getAttributeValues(attrSet, issuerStr, typeStr);
attributeValues = getAttributeValues(oldAttrSet, issuerStr, typeStr);
} catch (ParsingException e)
{
throw new RuntimeException(e);
}
newAttrSet = attrSet;
newAttrSet = oldAttrSet;
}
// see if we found any acceptable attributes
......@@ -902,30 +911,21 @@ public class BasicEvaluationCtx implements EvaluationCtx
return new EvaluationResult(new BagAttribute(type, attributeValues));
}
/*
* FIXME: this does not work as expected (Requirement #1) if AttributeFinder already called
* to find attribute with same (category,issuer,id,type) but result was actually an empty
* bag or an error. So we need to find a better way to indicate the attribute has already
* been searched for even if bad result. To solve this, we need to change the way we store
* attribute map in the request context.
*/
// No acceptable attribute found matching type/issuer... so ask the finder
// No acceptable attribute found matching type/issuer... so ask the finder via callHelper()
LOGGER.debug("Attribute id='{}' not in request context... querying AttributeFinder", id);
/*
* Code Updated [romain.guignard[at]thalesgroup.com] Allow to store value retrieved by an
* attributeFinder for a specific evaluationContext see also
* http://jira.theresis.thales:8180/browse/APPSEC-167
/**
* <code>newAttrSet</code> is linked to the eval context map. So this context is updated by
* storing the new value from callHelper() (call to AttributeFInder) in <code>newAttrSet</code>.
*/
final EvaluationResult result = callHelper(type, id, issuer, category, designatorType);
final AttributeValueType resultAttrVal = result.getAttributeValue();
if (resultAttrVal instanceof BagAttribute)
{
BagAttribute bagAttribute = (BagAttribute) resultAttrVal;
Iterator iter = bagAttribute.getValues().iterator();
while (iter.hasNext())
final BagAttribute bagAttribute = (BagAttribute) resultAttrVal;
for (final AttributeValue attributeValue : bagAttribute.getValues())
{
AttributeValueType attributeValue = (AttributeValueType) iter.next();
Attribute attribute = new Attribute();
// FIXME: do something better than creating one attribute per resulting value
final Attribute attribute = new Attribute();
attribute.setAttributeId(idStr);
attribute.setIssuer(issuerStr);
attribute.getAttributeValues().add(attributeValue);
......@@ -974,8 +974,7 @@ public class BasicEvaluationCtx implements EvaluationCtx
{
if (finder != null)
{
return finder.findAttribute(contextPath, namespaceNode, type, this, // XXX
xpathVersion);
return finder.findAttribute(contextPath, namespaceNode, type, this, xpathVersion);
}
LOGGER.warn("Context tried to invoke AttributeFinder but was " + "not configured with one");
......@@ -986,12 +985,12 @@ public class BasicEvaluationCtx implements EvaluationCtx
@Override
public Node getRequestRoot()
{
final DocumentBuilder docBuilder = BindingUtility.getDocumentBuilder(true);
final DocumentBuilder docBuilder = Utils.THREAD_LOCAL_NS_AWARE_DOC_BUILDER.get();
try
{
if (requestRoot == null)
{
Marshaller m = BindingUtility.XACML3_0_JAXB_CONTEXT.createMarshaller();
Marshaller m = PdpModelHandler.XACML_3_0_JAXB_CONTEXT.createMarshaller();
Document doc = docBuilder.newDocument();
m.marshal(request, doc);
requestRoot = doc.getDocumentElement();
......
/**
* Copyright (C) 2011-2014 Thales Services - ThereSIS - All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.xacml;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CacheManager {
private static net.sf.ehcache.CacheManager cacheManager;
private static CacheManager INSTANCE;
private static Object SYNCHRONE = new Object();
private boolean activate = false;
private int maxElementsInMemory = 100;
private boolean overflowToDisk = false;
private boolean eternal = false;
private int timeToLiveInSeconds = 10;
private int timeToIdleInSeconds = 5;
private Cache cache;
private Cache memoryOnlyCache;
private final static Logger LOGGER = LoggerFactory.getLogger(CacheManager.class);
public static CacheManager getInstance() {
if (null == INSTANCE) {
synchronized (SYNCHRONE) {
if (null == INSTANCE) {
INSTANCE = new CacheManager();
}
}
}
return INSTANCE;
}
public CacheManager() {
activate = false;
}
public CacheManager(List args) {
for (Map<String, String> myList : (ArrayList<Map<String, String>>) args) {
/*
* Cache configuration
*
* @author romain.ferrari[AT]thalesgroup.com
*/
if (myList.containsKey("activate")) {
activate = Boolean
.valueOf((Boolean.parseBoolean((String) myList
.get("activate"))));
}
else if (myList.containsKey("maxElementsInMemory")) {
maxElementsInMemory = (int) Integer
.parseInt((String) myList
.get("maxElementsInMemory"));
}
else if (myList.containsKey("overflowToDisk")) {
overflowToDisk = Boolean.valueOf((Boolean
.parseBoolean((String) myList
.get("overflowToDisk"))));
}
else if (myList.containsKey("eternal")) {
eternal = Boolean.valueOf((Boolean
.parseBoolean((String) myList.get("eternal"))));
}
else if (myList.containsKey("timeToLiveSeconds")) {
timeToLiveInSeconds = (int) Integer
.parseInt((String) myList
.get("timeToLiveSeconds"));
}
else if (myList.containsKey("timeToIdleSeconds")) {
timeToIdleInSeconds = (int) Integer
.parseInt((String) myList
.get("timeToIdleSeconds"));
}
}
/*
* Cache stuff
*
* @author romain.ferrari[AT]thalesgroup.com
*/
LOGGER.debug("Cache activated: {}", activate);
LOGGER.debug("maxElementsInMemory = {}", maxElementsInMemory);
LOGGER.debug("overflowToDisk: {}", overflowToDisk);
LOGGER.debug("eternal: {}", eternal);
LOGGER.debug("timeToLiveSeconds = {}", timeToLiveInSeconds);
LOGGER.debug("timeToIdleSeconds = {}", timeToIdleInSeconds);
// cacheManager = net.sf.ehcache.CacheManager.getInstance();
cacheManager = new net.sf.ehcache.CacheManager();
initCache();
}
public CacheManager(Map<String, String> args) {
if (args instanceof HashMap) {
Iterator it = args.keySet().iterator();
String val = null;
while (it.hasNext()) {
val = (String)it.next();
/*
* Cache configuration
*
* @author romain.ferrari[AT]thalesgroup.com
*/
if (("activate").equalsIgnoreCase(val)) {
activate = Boolean.valueOf((Boolean
.parseBoolean((String) args.get("activate"))));
} else if (("maxElementsInMemory").equalsIgnoreCase(val)) {
maxElementsInMemory = (int) Integer.parseInt((String) args
.get("maxElementsInMemory"));
} else if (("overflowToDisk").equalsIgnoreCase(val)) {
overflowToDisk = Boolean.valueOf((Boolean
.parseBoolean((String) args.get("overflowToDisk"))));
} else if (("eternal").equalsIgnoreCase(val)) {
eternal = Boolean.valueOf((Boolean
.parseBoolean((String) args.get("eternal"))));
} else if (("timeToLiveSeconds").equalsIgnoreCase(val)) {
timeToLiveInSeconds = (int) Integer.parseInt((String) args
.get("timeToLiveSeconds"));
} else if (("timeToIdleSeconds").equalsIgnoreCase(val)) {
timeToIdleInSeconds = (int) Integer.parseInt((String) args
.get("timeToIdleSeconds"));
}
}
}
/*
* Cache stuff
*
* @author romain.ferrari[AT]thalesgroup.com
*/
LOGGER.debug("Cache activated: {}", activate);
LOGGER.debug("maxElementsInMemory = {}", maxElementsInMemory);
LOGGER.debug("overflowToDisk: {}", overflowToDisk);
LOGGER.debug("eternal: {}", eternal);
LOGGER.debug("timeToLiveSeconds = {}", timeToLiveInSeconds);
LOGGER.debug("timeToIdleSeconds = {}", timeToIdleInSeconds);
initCache();
}
/**
* Cache initialization
*
* @author romain.ferrari[AT]thalesgroup.com
* @param name the name of the cache. Note that "default" is a reserved name for the defaultCache.
* @param maxElementsInMemory the maximum number of elements in memory, before they are evicted
* @param overflowToDisk whether to use the disk store
* @param eternal whether the elements in the cache are eternal, i.e. never expire
* @param timeToLiveSeconds the default amount of time to live for an element from its creation date
* @param timeToIdleSeconds the default amount of time to live for an element from its last accessed or modified date
*/
private void initCache() {
//NOTE: Create a Cache and add it to the static CacheManager, then use it.
memoryOnlyCache = new Cache("AuthZForce", maxElementsInMemory, overflowToDisk, eternal, timeToLiveInSeconds, timeToIdleInSeconds);
cacheManager.addCache(memoryOnlyCache);
cache = cacheManager.getCache("AuthZForce");
}
/**
* Used to clear the cache.
*
* @return true if ok, false if a problem occured
*/
public boolean invalidateCache() {
if (cache != null && cache.getSize() > 0) {
LOGGER.info("Invalidating cache");
this.cache.removeAll();
return true;
}
return false;
}
/**
* Searching the cache for the <code>hash</code> as key. A Object is returned if the
* matching Request is found
*
* @param hash symbolising the object as a unique object
*
* @return Object matching the hash
*/
public Object checkCache(String hash) {
Element myElt;
LOGGER.debug("checkCache with {}", hash);
myElt = cache.get(hash);
if (myElt != null) {
return myElt.getObjectValue();
}
return null;
}
/**
* Updating the cache content.
*
* @param hash
* @param storedObject
*/
public void updateCache(String hash, Object storedObject) {
LOGGER.debug("Updating cache with: {}", hash);
cache.put(new Element(hash, storedObject));
}
public static net.sf.ehcache.CacheManager getCacheManager() {
return cacheManager;
}
public static void setCacheManager(net.sf.ehcache.CacheManager cacheManager) {
CacheManager.cacheManager = cacheManager;
}
public boolean isActivate() {
return activate;
}
public void setActivate(boolean activate) {
this.activate = activate;
}
public int getMaxElementsInMemory() {
return maxElementsInMemory;
}
public void setMaxElementsInMemory(int maxElementsInMemory) {
this.maxElementsInMemory = maxElementsInMemory;
}
public boolean isOverflowToDisk() {
return overflowToDisk;
}
public void setOverflowToDisk(boolean overflowToDisk) {
this.overflowToDisk = overflowToDisk;
}
public boolean isEternal() {
return eternal;
}
public void setEternal(boolean eternal) {
this.eternal = eternal;
}
public int getTimeToLiveInSeconds() {
return timeToLiveInSeconds;
}
public void setTimeToLiveInSeconds(int timeToLiveInSeconds) {
this.timeToLiveInSeconds = timeToLiveInSeconds;
}
public int getTimeToIdleInSeconds() {
return timeToIdleInSeconds;
}
public void setTimeToIdleInSeconds(int timeToIdleInSeconds) {
this.timeToIdleInSeconds = timeToIdleInSeconds;
}
public Cache getCache() {
return cache;
}
public void setCache(Cache cache) {
this.cache = cache;
}
public Cache getMemoryOnlyCache() {
return memoryOnlyCache;
}
public void setMemoryOnlyCache(Cache memoryOnlyCache) {
this.memoryOnlyCache = memoryOnlyCache;
}
}
......@@ -51,6 +51,8 @@ import javax.xml.bind.JAXBContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.validation.Schema;
import net.sf.ehcache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
......@@ -81,7 +83,7 @@ import com.sun.xacml.cond.cluster.FunctionCluster;
import com.sun.xacml.finder.AttributeFinder;
import com.sun.xacml.finder.PolicyFinder;
import com.sun.xacml.finder.ResourceFinder;
import com.thalesgroup.authzforce.BindingUtility;
import com.thalesgroup.appsec.util.Utils;
/**
* This class supports run-time loading of configuration data. It loads the
......@@ -387,8 +389,7 @@ public class ConfigurationStore {
* Private helper that parses the file and sets up the DOM tree.
*/
private Node getRootNode(File configFile) throws ParsingException {
final DocumentBuilder threadLocalDocBuilder = BindingUtility
.getDocumentBuilder(true);
final DocumentBuilder threadLocalDocBuilder = Utils.THREAD_LOCAL_NS_AWARE_DOC_BUILDER.get();
Document doc = null;
try {
......@@ -470,13 +471,13 @@ public class ConfigurationStore {
ResourceFinder rsrcFinder = new ResourceFinder();
rsrcFinder.setModules(rsrcModules);
CacheManager cacheManager = cacheModules.isEmpty() ? null
: (CacheManager) cacheModules.get(0);
Cache cache = cacheModules.isEmpty() ? null
: (Cache) cacheModules.get(0);
// CacheManager cacheManager = CacheManager.getInstance();
// return new PDPConfig(attrFinder, policyFinder, rsrcFinder);
return new PDPConfig(attrFinder, policyFinder, rsrcFinder, cacheManager);
return new PDPConfig(attrFinder, policyFinder, rsrcFinder, cache);
}
/**
......
......@@ -55,7 +55,6 @@ import com.sun.xacml.cond.xacmlv3.EvaluationResult;
*
* @since 1.0
* @author Seth Proctor
* @author Romain Ferrari
*/
public interface EvaluationCtx {
......
......@@ -62,7 +62,7 @@ import com.sun.xacml.cond.Evaluatable;
import com.sun.xacml.cond.xacmlv3.EvaluationResult;
import com.sun.xacml.cond.xacmlv3.ExpressionTools;
import com.sun.xacml.ctx.Result;
import com.thalesgroup.authzforce.BindingUtility;
import com.thalesgroup.authzforce.core.PdpModelHandler;
/**
* Represents the ObligationType XML type in XACML. This also stores all the AttriubteAssignmentType
......@@ -374,7 +374,7 @@ public class Obligation extends oasis.names.tc.xacml._3_0.core.schema.wd_17.Obli
PrintStream out = new PrintStream(output);
try
{
Marshaller u = BindingUtility.XACML3_0_JAXB_CONTEXT.createMarshaller();
Marshaller u = PdpModelHandler.XACML_3_0_JAXB_CONTEXT.createMarshaller();
u.marshal(this, out);
} catch (Exception e)
{
......
/**
* Copyright (C) 2011-2014 Thales Services - ThereSIS - All rights reserved.
* Copyright (C) 2011-2014 Thales Services SAS - All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -30,12 +30,8 @@ import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.thalesgroup.authzforce.BindingUtility;
import com.thalesgroup.authzforce.core.PdpModelHandler;
/**
* @author Romain Ferrari
*
*/
public class ObligationExpressions extends oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressions {
/**
......@@ -60,7 +56,7 @@ public class ObligationExpressions extends oasis.names.tc.xacml._3_0.core.schema
if (node.getNodeName().equals("ObligationExpression")) {
final JAXBElement<oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressions> match;
try {
Unmarshaller u = BindingUtility.XACML3_0_JAXB_CONTEXT.createUnmarshaller();
Unmarshaller u = PdpModelHandler.XACML_3_0_JAXB_CONTEXT.createUnmarshaller();
match = u.unmarshal(root, oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressions.class);
obligationExpressions = match.getValue();
} catch (Exception e) {
......
......@@ -41,6 +41,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Attribute;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
import oasis.names.tc.xacml._3_0.core.schema.wd_17.Attributes;
......@@ -85,7 +87,7 @@ public class PDP
// the logger we'll use for all messages
private static final Logger LOGGER = LoggerFactory.getLogger(PDP.class);
private static CacheManager cacheManager;
private static Cache cache;
private static PDP authzforce;
......@@ -130,17 +132,7 @@ public class PDP
resourceFinder = config.getResourceFinder();
cacheManager = config.getCacheManager();
/*
* Cache initialization
*
* AUTHOR: romain.ferrari[AT]thalesgroup.com
*/
if (cacheManager.isActivate())
{
cacheManager = CacheManager.getInstance();
}
cache = config.getCache();
}
/**
......@@ -180,8 +172,6 @@ public class PDP
/**
* Used to initiate a reload of the policies without reload the whole server
*
* @author romain.ferrari[AT]thalesgroup.com
* @return the PolicyFinder used by the PDP
*/
public PolicyFinder getPolicyFinder()
......@@ -389,36 +379,30 @@ public class PDP
private ResponseCtx evaluatePrivate(Request request)
{
String hash = "";
// try to create the EvaluationCtx out of the request
// FIXME: finish implementation
try
{
BasicEvaluationCtx myEvaluationCtx = new BasicEvaluationCtx(request, attributeFinder, PolicyMetaData.XACML_VERSION_3_0);
/*
*
*/
// @author: romain.ferrari@thalesgroup.com
final BasicEvaluationCtx evalCtx = new BasicEvaluationCtx(request, attributeFinder, PolicyMetaData.XACML_VERSION_3_0);
// Using the cache if defined
if (cacheManager.isActivate())
if (cache != null && !cache.isDisabled())
{
// FIXME: simply use request.hashCode()
hash = getHashCode(request);
ResponseCtx cacheResult = (ResponseCtx) cacheManager.checkCache(getHashCode(