001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: PolicyDecision.java,v 1.3 2008/06/25 05:43:44 qcheng Exp $ 026 * 027 * Portions Copyrighted 2011-2014 ForgeRock AS. 028 */ 029package com.sun.identity.policy; 030 031import java.util.Map; 032import java.util.HashMap; 033import java.util.Set; 034import java.util.Iterator; 035import java.util.Collections; 036import com.sun.identity.shared.xml.XMLUtils; 037import com.sun.identity.sm.AttributeSchema; 038import org.w3c.dom.*; 039 040 041/** 042 * The <code>PolicyDecision</code> class represents the result of a policy 043 * evaluation. 044 * 045 * @supported.api 046 * @deprecated since 12.0.0 047 */ 048@Deprecated 049public class PolicyDecision { 050 051 static final String POLICY_DECISION = "PolicyDecision"; 052 static final String RESPONSE_DECISIONS = "ResponseDecisions"; 053 054 //added in 7.0 for attributes provided by policy response providers 055 static final String RESPONSE_ATTRIBUTES = "ResponseAttributes"; 056 057 Map actionDecisions = new HashMap(); 058 private Map responseDecisions; 059 private Map responseAttributes; 060 private long timeToLive = Long.MAX_VALUE; 061 private boolean advicesAreSet = false; 062 063 /** 064 * Default constructor. 065 * @supported.api 066 */ 067 public PolicyDecision() { 068 } 069 070 /** 071 * Gets the <code>Map</code> of action decisions associated 072 * with this policy decision. The 073 * action name is the key to the Map. The value for each key is an 074 * <code>ActionDecision</code>. 075 * 076 * @return the <code>Map</code> of action decisions associated 077 * with this policy decision. The 078 * action name is the key to the Map. The value for each key is an 079 * <code>ActionDecision</code>. 080 * @supported.api 081 */ 082 public Map getActionDecisions() { 083 return actionDecisions; 084 } 085 086 /** 087 * Add an <code>ActionDecision</code> to the <code>PolicyDecision</code> 088 * These are the rules followed to add action decision: 089 * If the action schema has boolean syntax, boolean false value 090 * overrides boolean true value. The time to live of boolean false 091 * value overrides the time to live of boolean true value. 092 * Otherwise, action values are simply aggregated. Time to live 093 * is set to the minimum of time to live(s) of all values of the 094 * action. 095 * 096 * @param newActionDecision an <code>ActionDecision</code> to be added. 097 * @param resourceType <code>ServiceType</code> representing the 098 * service which provides the schema for the action. 099 * 100 */ 101 102 void addActionDecision(ActionDecision newActionDecision, ServiceType 103 resourceType) { 104 String action = newActionDecision.getActionName(); 105 ActionDecision oldActionDecision 106 = (ActionDecision) actionDecisions.get(action); 107 if ( oldActionDecision == null ) { 108 addActionDecision(newActionDecision); 109 } else { 110 ActionSchema actionSchema = null; 111 AttributeSchema.Syntax actionSyntax = null; 112 try { 113 actionSchema = resourceType.getActionSchema(action); 114 actionSyntax = actionSchema.getSyntax(); 115 } catch(InvalidNameException e) { 116 PolicyManager.debug.error( 117 "can not find action schmea for action = " 118 + action, e ); 119 } 120 if (!AttributeSchema.Syntax.BOOLEAN.equals( 121 actionSyntax)) { 122 addActionDecision(newActionDecision); 123 } else { //boolean valued action 124 String falseValue = actionSchema.getFalseValue(); 125 String trueValue = actionSchema.getTrueValue(); 126 addActionDecision(newActionDecision, trueValue, falseValue); 127 } 128 } 129 } 130 131 /** 132 * Add an <code>ActionDecision</code> to the <code>PolicyDecision</code> 133 * using the provided <code>trueValue</code> and <code>falseValue</code> 134 * These are the rules followed to add action decision: 135 * Boolean false value overrides boolean true value. The time to live 136 * of boolean false value overrides the time to live of boolean true value. 137 * Otherwise, action values are simply aggregated. Time to live 138 * is set to the minimum of time to live(s) of all values of the 139 * action. 140 * 141 * @param newActionDecision an <code>ActionDecision</code> to be added. 142 * @param trueValue <code>String</code> representing the </code>true</code> 143 * value in the action schema. 144 * @param falseValue <code>String</code> representing the 145 * </code>false</code> value in the action schema. 146 * 147 */ 148 public void addActionDecision(ActionDecision newActionDecision, 149 String trueValue, String falseValue) { 150 String action = newActionDecision.getActionName(); 151 ActionDecision oldActionDecision 152 = (ActionDecision) actionDecisions.get(action); 153 if ( (oldActionDecision == null) 154 || (trueValue == null) || (falseValue == null)) { 155 addActionDecision(newActionDecision); 156 } else { //boolean valued action 157 long newTtl = newActionDecision.getTimeToLive(); 158 long oldTtl = oldActionDecision.getTimeToLive(); 159 Set oldActionValues = oldActionDecision.getValues(); 160 Set newActionValues = newActionDecision.getValues(); 161 Map advices = null; 162 Map oldAdvices = oldActionDecision.getAdvices(); 163 Map newAdvices = newActionDecision.getAdvices(); 164 advices = PolicyUtils.addMapToMap(oldAdvices, newAdvices); 165 if ( (oldActionValues != null) 166 && (oldActionValues.contains(falseValue)) ) { 167 if ( (newActionValues != null) 168 && newActionValues.contains(falseValue) ) { 169 //both old and new values are false 170 //get the ttl to max of newTtl and oldTtl 171 oldActionDecision.setTimeToLive(Math.max(newTtl, oldTtl)); 172 } 173 174 /* else block not required here since 175 oldActionDecision does not need to change as it is false 176 and newActionDecision is null or true 177 */ 178 } else if ( (oldActionValues != null) 179 && oldActionValues.contains(trueValue) ) { 180 if ( (newActionValues != null) 181 && newActionValues.contains(falseValue) ) { 182 actionDecisions.put(action, newActionDecision); 183 } else if ( newActionDecision.getValues().contains(trueValue) ) { 184 //get the ttl to max of newTtl and oldTtl 185 oldActionDecision.setTimeToLive(Math.max(newTtl, oldTtl)); 186 } 187 } else { 188 actionDecisions.put(action, newActionDecision); 189 } 190 ActionDecision ad = (ActionDecision) actionDecisions.get(action); 191 ad.setAdvices(advices); 192 setTimeToLive(); 193 } 194 } 195 196 /** 197 * Adds an action decision to this object 198 * if there is already an existing actionDecision associated with the 199 * action name in the param <code>actionDecision</code>, merges 200 * the values of the new decision with the existing one, 201 * changing the time to live for the decision appropriately. 202 * 203 * @param actionDecision action decision to be added 204 * @supported.api 205 */ 206 public void addActionDecision(ActionDecision actionDecision) { 207 ActionDecision oldDecision = 208 (ActionDecision) actionDecisions.get( 209 actionDecision.getActionName()); 210 if ( oldDecision == null ) { 211 actionDecisions.put(actionDecision.getActionName(), 212 actionDecision); 213 } else { 214 Set oldValues = oldDecision.getValues(); 215 if ( (oldValues == Collections.EMPTY_SET) 216 || ( oldValues == null) ) { 217 oldDecision.setValues(actionDecision.getValues()); 218 } else { 219 oldValues.addAll(actionDecision.getValues()); 220 } 221 if ( actionDecision.getTimeToLive() 222 < oldDecision.getTimeToLive() ) { 223 oldDecision.setTimeToLive(actionDecision.getTimeToLive()); 224 } 225 PolicyUtils.appendMapToMap(actionDecision.getAdvices(), 226 oldDecision.getAdvices()); 227 } 228 setTimeToLive(); 229 } 230 231 /** 232 * Gets a String representation of this <code>PolicyDecision</code> 233 * @return a String representation of this <code>PolicyDecision</code> 234 * 235 * @supported.api 236 */ 237 public String toString() { 238 StringBuilder sb = new StringBuilder(); 239 if ((responseAttributes != null) && 240 (responseAttributes != Collections.EMPTY_MAP)) { 241 Iterator attrNames = responseAttributes.keySet().iterator(); 242 while ( attrNames.hasNext() ) { 243 String attrName = (String) attrNames.next(); 244 Set attrValues = (Set) responseAttributes.get(attrName); 245 sb.append(attrName).append("=").append(attrValues).append("\n"); 246 } 247 } 248 Iterator actionNames = actionDecisions.keySet().iterator(); 249 while ( actionNames.hasNext() ) { 250 String actionName = (String) actionNames.next(); 251 ActionDecision actionDecision = 252 (ActionDecision) actionDecisions.get(actionName); 253 Set actionValues = (Set) actionDecision.getValues(); 254 sb.append(actionName).append("=").append(actionValues).append("\n"); 255 } 256 return sb.toString(); 257 } 258 259 260 /** 261 * Gets an XML representation of this object 262 * @return an XML representation of this object 263 * 264 * @supported.api 265 */ 266 public String toXML() { 267 StringBuilder sb = new StringBuilder(300); 268 sb.append("<").append(POLICY_DECISION) 269 /* 270 .append(" ").append("timeToLive") 271 .append("=\"").append(timeToLive).append("\"") 272 .append(" ").append("hasAdvices") 273 .append("=\"").append(hasAdvices()).append("\"") 274 */ 275 .append(">").append(PolicyUtils.CRLF); 276 if ((responseAttributes != null) && 277 (responseAttributes != Collections.EMPTY_MAP)) { 278 sb.append("<").append(RESPONSE_ATTRIBUTES); 279 sb.append(">").append(PolicyUtils.CRLF); 280 sb.append(PolicyUtils.mapToXMLString(responseAttributes)); 281 sb.append("<").append("/").append(RESPONSE_ATTRIBUTES); 282 sb.append(">").append(PolicyUtils.CRLF); 283 } 284 Iterator actionNames = actionDecisions.keySet().iterator(); 285 while ( actionNames.hasNext() ) { 286 String actionName = (String) actionNames.next(); 287 ActionDecision actionDecision = (ActionDecision) 288 actionDecisions.get(actionName); 289 sb.append(actionDecision.toXML()); 290 } 291 if (responseDecisions != null) { 292 sb.append("<").append(RESPONSE_DECISIONS).append(">") 293 .append(PolicyUtils.CRLF); 294 sb.append(PolicyUtils.mapToXMLString(responseDecisions)); 295 sb.append("</").append(RESPONSE_DECISIONS).append(">") 296 .append(PolicyUtils.CRLF); 297 } 298 sb.append("</").append(POLICY_DECISION).append(">"); 299 sb.append(PolicyUtils.CRLF); 300 return sb.toString(); 301 } 302 303 /** 304 * Gets a PolicyDecision given corresponding XML node 305 * @param policyDecisionNode XML node for the policy decision 306 * @return policy decision based on the XML node 307 */ 308 public static PolicyDecision parsePolicyDecision(Node policyDecisionNode) 309 throws PolicyException 310 { 311 PolicyDecision policyDecision = new PolicyDecision(); 312 Set nodeSet = XMLUtils.getChildNodes(policyDecisionNode, 313 ActionDecision.ACTION_DECISION); 314 if (nodeSet == null) { 315 PolicyManager.debug.error("parsePolicyDecision: Required element " 316 + "not found in policy decision node:" 317 + ActionDecision.ACTION_DECISION); 318 Object [] args = { ActionDecision.ACTION_DECISION }; 319 throw new PolicyException(ResBundleUtils.rbName, 320 "missing_element", args, null); 321 } else { 322 Iterator nodes = nodeSet.iterator(); 323 while (nodes.hasNext()) { 324 Node node = (Node)nodes.next(); 325 ActionDecision actionDecision = 326 ActionDecision.parseActionDecision(node); 327 policyDecision.addActionDecision(actionDecision); 328 } 329 } 330 Set resposeAttrsSet = XMLUtils.getChildNodes(policyDecisionNode, 331 RESPONSE_ATTRIBUTES); 332 if ( (resposeAttrsSet != null) && !resposeAttrsSet.isEmpty() ) { 333 Node node = (Node) resposeAttrsSet.iterator().next(); 334 Map responseAttrsMap = PolicyUtils.parseAttributeValuePairs(node); 335 policyDecision.setResponseAttributes(responseAttrsMap); 336 } 337 Set responseNodeSet = XMLUtils.getChildNodes(policyDecisionNode, 338 RESPONSE_DECISIONS); 339 if ( (responseNodeSet != null) && !responseNodeSet.isEmpty() ) { 340 Node node = (Node) responseNodeSet.iterator().next(); 341 Map responseMap = PolicyUtils.parseAttributeValuePairs(node); 342 policyDecision.setResponseDecisions(responseMap); 343 } 344 return policyDecision; 345 } 346 347 /** 348 * 349 * Gets response decisions associated with this policy decision 350 * @return <code>Map</code> representing the response decisions associated 351 * with this policy decision 352 * 353 */ 354 public Map getResponseDecisions() { 355 return responseDecisions; 356 } 357 358 /** 359 * 360 * Sets response decisions associated with this policy decision 361 * @param responseDecisions A <code>Map</code> representing response 362 * decisions associated with this policy decision 363 */ 364 public void setResponseDecisions(Map responseDecisions) { 365 this.responseDecisions = responseDecisions; 366 } 367 368 369 /** 370 * 371 * Gets response attributes associated with this policy decision. 372 * Response attributes are computed as an aggregation of the return 373 * <code>Map</code>(s) of the <code>ResponseProvider</code> objects 374 * associated with the policy obtained via the getResponseDecision() call. 375 * @return the <code>Map</code> of response attributes associated with 376 * this policy decision. 377 * 378 */ 379 public Map getResponseAttributes() { 380 return responseAttributes; 381 } 382 383 /** 384 * 385 * Sets response attributes associated with this policy decision 386 * @param responseAttributes <code>Map</code> of attribute value pairs 387 * associated with this policy decision. 388 */ 389 public void setResponseAttributes(Map responseAttributes) { 390 this.responseAttributes = responseAttributes; 391 } 392 /** 393 * Makes a copy of this object 394 * 395 * @return a copied instance 396 */ 397 public Object clone() { 398 PolicyDecision clone = new PolicyDecision(); 399 clone.actionDecisions = new HashMap(actionDecisions.size()); 400 Iterator actionDecisionIter = actionDecisions.keySet().iterator(); 401 while (actionDecisionIter.hasNext()) { 402 String key = (String) actionDecisionIter.next(); 403 ActionDecision ad = (ActionDecision) actionDecisions.get(key); 404 clone.addActionDecision((ActionDecision)ad.clone()); 405 } 406 407 if (responseDecisions != null) { 408 clone.responseDecisions = new HashMap(responseDecisions.size()); 409 Iterator responseDecisionsIter = 410 responseDecisions.keySet().iterator(); 411 while (responseDecisionsIter.hasNext()) { 412 String key = (String) responseDecisionsIter.next(); 413 clone.responseDecisions.put(key, responseDecisions.get(key)); 414 } 415 } 416 if (responseAttributes != null) { 417 clone.responseAttributes = new HashMap(responseAttributes.size()); 418 Iterator responseAttributesIter = 419 responseAttributes.keySet().iterator(); 420 while (responseAttributesIter.hasNext()) { 421 String key = (String) responseAttributesIter.next(); 422 clone.responseAttributes.put(key, responseAttributes.get(key)); 423 } 424 } 425 return clone; 426 } 427 428 429 /** 430 * Gets the GMT time in milliseconds since epoch when this object is to 431 * be treated as expired. That is the policy decision would likely 432 * be different after that time. 433 * This is computed as a result of <code>SimpleTimeCondition</code>s 434 * specified in the <code>Policy</code> definition. 435 * 436 * @return time to live 437 */ 438 public long getTimeToLive() { 439 return timeToLive; 440 } 441 442 /** 443 * Sets the <code>timeToLive</code> value of the policy decision to the 444 * smallest of <code>timeToLive(s)<code> of contained 445 * <code>ActionDecision(s)<code>. Also sets value of 446 * <code>advicesAreSet</code>. This is set to <code>true</code> 447 * if any of the contained action decision(s) has advice defined. 448 */ 449 private void setTimeToLive() { 450 timeToLive = Long.MAX_VALUE; 451 advicesAreSet = false; 452 Iterator actionDecisionIter = actionDecisions.keySet().iterator(); 453 while (actionDecisionIter.hasNext()) { 454 String key = (String) actionDecisionIter.next(); 455 ActionDecision ad = (ActionDecision) actionDecisions.get(key); 456 long actionTtl = ad.getTimeToLive(); 457 if ( actionTtl < timeToLive) { 458 timeToLive = actionTtl; 459 } 460 advicesAreSet = advicesAreSet || 461 ((ad.getAdvices()) != null) && (!(ad.getAdvices().isEmpty())); 462 } 463 } 464 465 /** 466 * Sets the timeToLive value of the policy decision. 467 * 468 * @param ttl timeToLive value to be set 469 */ 470 void setTimeToLive(long ttl) { 471 timeToLive = ttl; 472 } 473 474 /** 475 * Checks wether advices are set in this object 476 * @return <code>true</code>, if advices are set, else <code>false</code> 477 */ 478 public boolean hasAdvices() { 479 return advicesAreSet; 480 } 481}
Copyright © 2010-2017, ForgeRock All Rights Reserved.