/* Copyright 2012-2015 SAP SE
*
* 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 eu.aniketos.securebpmn.xacml.combine;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
import eu.aniketos.securebpmn.xacml.AnalysisCtx;
import com.sun.xacml.ConfigurationStore;
import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.Rule;
import com.sun.xacml.combine.CombinerElement;
import com.sun.xacml.combine.CombinerParameter;
import com.sun.xacml.combine.PermitOverridesRuleAlg;
import com.sun.xacml.combine.RuleCombinerElement;
import com.sun.xacml.ctx.Result;
public class AnalysisPermitOverridesRuleAlg extends PermitOverridesRuleAlg {
public AnalysisPermitOverridesRuleAlg() {
super();
}
public void setConfigurationStore(ConfigurationStore conf) {
//this.conf = conf;
}
/**
* Protected constructor used by the ordered version of this algorithm.
*
* @param identifier the algorithm's identifier
*/
protected AnalysisPermitOverridesRuleAlg(URI identifier) {
super(identifier);
}
public Result combine(EvaluationCtx context, List<CombinerParameter> parameters,
List<CombinerElement> ruleElements) {
boolean atLeastOneError = false;
boolean potentialPermit = false;
boolean atLeastOneDeny = false;
Result firstIndeterminateResult = null;
Iterator<CombinerElement> it = ruleElements.iterator();
Result finalResult = null;
while (it.hasNext()) {
Rule rule = ((RuleCombinerElement)(it.next())).getRule();
Result result = rule.evaluate(context);
int value = result.getDecision();
// if there was a value of PERMIT, then regardless of what
// else we've seen, we always return PERMIT
if (value == Result.DECISION_PERMIT) {
if ( ((AnalysisCtx)context).getEvalInfo().isMissingAttribute() ) {
if ( finalResult == null) {
finalResult = result;
}
} else {
return result;
}
}
// if it was INDETERMINATE, then we couldn't figure something
// out, so we keep track of these cases...
if (value == Result.DECISION_INDETERMINATE) {
atLeastOneError = true;
// there are no rules about what to do if multiple cases
// cause errors, so we'll just return the first one
if (firstIndeterminateResult == null) {
firstIndeterminateResult = result;
}
// if the Rule's effect is PERMIT, then we can't let this
// alg return DENY, since this Rule might have permitted
// if it could do its stuff
if (rule.getEffect() == Result.DECISION_PERMIT) {
potentialPermit = true;
}
} else {
// keep track of whether we had at least one rule that
// actually pertained to the request
if (value == Result.DECISION_DENY) {
atLeastOneDeny = true;
}
}
}
if ( finalResult != null ) {
return finalResult;
}
// we didn't explicitly PERMIT, but we might have had some Rule
// been evaluated, so we have to return INDETERMINATE
if (potentialPermit) {
return firstIndeterminateResult;
}
// some Rule said DENY, so since nothing could have permitted,
// we return DENY
if (atLeastOneDeny) {
return new Result(Result.DECISION_DENY,
context);
}
// we didn't find anything that said DENY, but if we had a
// problem with one of the Rules, then we're INDETERMINATE
if (atLeastOneError) {
return firstIndeterminateResult;
}
// if we hit this point, then none of the rules actually applied
// to us, so we return NOT_APPLICABLE
return new Result(Result.DECISION_NOT_APPLICABLE,
context);
}
}