/* * Copyright (c) WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. licenses this file to you 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 org.wso2.carbon.identity.entitlement.policy.collection; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.balana.AbstractPolicy; import org.wso2.balana.MatchResult; import org.wso2.balana.Policy; import org.wso2.balana.PolicyReference; import org.wso2.balana.PolicySet; import org.wso2.balana.VersionConstraints; import org.wso2.balana.combine.PolicyCombiningAlgorithm; import org.wso2.balana.ctx.EvaluationCtx; import org.wso2.carbon.identity.entitlement.EntitlementException; import java.net.URI; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; /** * simple implementation of Policy collection interface. This uses in-memory map to maintain policies * policy versions are not maintained by this */ public class SimplePolicyCollection implements PolicyCollection { private static Log log = LogFactory.getLog(SimplePolicyCollection.class); /** * the actual collection of policies * to maintain the order of the policies, <code>LinkedHashMap</code> has been used. * Map with policy identifier policy as <code>AbstractPolicy</code> object */ private LinkedHashMap<URI, AbstractPolicy> policyCollection = new LinkedHashMap<URI, AbstractPolicy>(); /** * the optional combining algorithm used when wrapping multiple policies * if no algorithm is defined, only one applicable algorithm is used */ private PolicyCombiningAlgorithm combiningAlg; /** * the optional policy id used when wrapping multiple policies */ private URI parentId; @Override public void init(Properties properties) throws Exception { String parentIdProperty = properties.getProperty("parentId"); if (parentIdProperty != null) { parentId = new URI(parentIdProperty); } } @Override public boolean addPolicy(AbstractPolicy policy) { return addPolicy(policy.getId(), policy); } @Override public AbstractPolicy getEffectivePolicy(EvaluationCtx context) throws EntitlementException { // setup a list of matching policies ArrayList<AbstractPolicy> list = new ArrayList<AbstractPolicy>(); for (Map.Entry<URI, AbstractPolicy> entry : policyCollection.entrySet()) { AbstractPolicy policy = entry.getValue(); // see if we match MatchResult match = policy.match(context); int result = match.getResult(); // if there was an error, we stop right away if (result == MatchResult.INDETERMINATE) { log.error(match.getStatus().getMessage()); throw new EntitlementException(match.getStatus().getMessage()); } // if we matched, we keep track of the matching policy... if (result == MatchResult.MATCH) { // ...first checking if this is the first match and if // we automatically nest policies if (log.isDebugEnabled()) { log.debug("Matching XACML policy found " + policy.getId().toString()); } if ((combiningAlg == null) && (list.size() > 0)) { log.error("Too many applicable top-level policies"); throw new EntitlementException("Too many applicable top-level policies"); } list.add(policy); } } // no errors happened during the search, so now take the right // action based on how many policies we found switch (list.size()) { case 0: if (log.isDebugEnabled()) { log.debug("No matching XACML policy found"); } return null; case 1: return ((AbstractPolicy) (list.get(0))); default: return new PolicySet(parentId, combiningAlg, null, list); } } @Override public AbstractPolicy getPolicy(URI policyId) { return policyCollection.get(policyId); } @Override public AbstractPolicy getPolicy(URI identifier, int type, VersionConstraints constraints) { AbstractPolicy policy = policyCollection.get(identifier); if (policy != null) { // we found a valid version, so see if it's the right kind, // and if it is then we return it if (type == PolicyReference.POLICY_REFERENCE) { if (policy instanceof Policy) return policy; } else { if (policy instanceof PolicySet) return policy; } } return null; } private synchronized boolean addPolicy(URI identifier, AbstractPolicy policy) { return policyCollection.put(identifier, policy) != null; } @Override public void setPolicyCombiningAlgorithm(PolicyCombiningAlgorithm algorithm) { this.combiningAlg = algorithm; } @Override public boolean deletePolicy(String policyId) { return this.policyCollection.remove(policyId) != null ; } @Override public LinkedHashMap getPolicyMap() { return this.policyCollection; } @Override public void setPolicyMap(LinkedHashMap policyMap) { this.policyCollection = policyMap ; } }