Source code: com/sun/xacml/cond/ConditionSetFunction.java
1
2 /*
3 * @(#)ConditionSetFunction.java
4 *
5 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistribution of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistribution in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
18 * be used to endorse or promote products derived from this software without
19 * specific prior written permission.
20 *
21 * This software is provided "AS IS," without a warranty of any kind. ALL
22 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
23 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
24 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
25 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
26 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
27 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
28 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
29 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
30 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
31 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * You acknowledge that this software is not designed or intended for use in
34 * the design, construction, operation or maintenance of any nuclear facility.
35 */
36
37 package com.sun.xacml.cond;
38
39 import com.sun.xacml.EvaluationCtx;
40
41 import com.sun.xacml.attr.AttributeValue;
42 import com.sun.xacml.attr.BagAttribute;
43 import com.sun.xacml.attr.BooleanAttribute;
44
45 import java.util.Collections;
46 import java.util.HashMap;
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Set;
51
52
53 /**
54 * Specific <code>SetFunction</code> class that supports all of the
55 * condition set functions: type-at-least-one-member-of, type-subset, and
56 * type-set-equals.
57 *
58 * @since 1.2
59 * @author Seth Proctor
60 */
61 public class ConditionSetFunction extends SetFunction
62 {
63
64 // private identifiers for the supported functions
65 private static final int ID_BASE_AT_LEAST_ONE_MEMBER_OF = 0;
66 private static final int ID_BASE_SUBSET = 1;
67 private static final int ID_BASE_SET_EQUALS = 2;
68
69 // mapping of function name to its associated id and parameter type
70 private static HashMap idMap;
71 private static HashMap typeMap;
72
73 // the actual supported ids
74 private static Set supportedIds;
75
76 /**
77 * Static initializer that sets up the paramater info for all the
78 * supported functions.
79 */
80 static {
81 idMap = new HashMap();
82 typeMap = new HashMap();
83
84 for (int i = 0; i < baseTypes.length; i++) {
85 String baseName = FUNCTION_NS + simpleTypes[i];
86 String baseType = baseTypes[i];
87
88 idMap.put(baseName + NAME_BASE_AT_LEAST_ONE_MEMBER_OF,
89 new Integer(ID_BASE_AT_LEAST_ONE_MEMBER_OF));
90 idMap.put(baseName + NAME_BASE_SUBSET,
91 new Integer(ID_BASE_SUBSET));
92 idMap.put(baseName + NAME_BASE_SET_EQUALS,
93 new Integer(ID_BASE_SET_EQUALS));
94
95 typeMap.put(baseName + NAME_BASE_AT_LEAST_ONE_MEMBER_OF, baseType);
96 typeMap.put(baseName + NAME_BASE_SUBSET, baseType);
97 typeMap.put(baseName + NAME_BASE_SET_EQUALS, baseType);
98 }
99
100 supportedIds = Collections.
101 unmodifiableSet(new HashSet(idMap.keySet()));
102
103 idMap.put(NAME_BASE_AT_LEAST_ONE_MEMBER_OF,
104 new Integer(ID_BASE_AT_LEAST_ONE_MEMBER_OF));
105 idMap.put(NAME_BASE_SUBSET, new Integer(ID_BASE_SUBSET));
106 idMap.put(NAME_BASE_SET_EQUALS, new Integer(ID_BASE_SET_EQUALS));
107 };
108
109 /**
110 * Constructor that is used to create one of the condition standard
111 * set functions. The name supplied must be one of the standard XACML
112 * functions supported by this class, including the full namespace,
113 * otherwise an exception is thrown. Look in <code>SetFunction</code>
114 * for details about the supported names.
115 *
116 * @param functionName the name of the function to create
117 *
118 * @throws IllegalArgumentException if the function is unknown
119 */
120 public ConditionSetFunction(String functionName) {
121 super(functionName, getId(functionName), getArgumentType(functionName),
122 BooleanAttribute.identifier, false);
123 }
124
125 /**
126 * Constructor that is used to create instances of condition set
127 * functions for new (non-standard) datatypes. This is equivalent to
128 * using the <code>getInstance</code> methods in <code>SetFunction</code>
129 * and is generally only used by the run-time configuration code.
130 *
131 * @param functionName the name of the new function
132 * @param datatype the full identifier for the supported datatype
133 * @param functionType which kind of Set function, based on the
134 * <code>NAME_BASE_*</code> fields
135 */
136 public ConditionSetFunction(String functionName, String datatype,
137 String functionType) {
138 super(functionName, getId(functionName), datatype,
139 BooleanAttribute.identifier, false);
140 }
141
142 /**
143 * Private helper that returns the internal identifier used for the
144 * given standard function.
145 */
146 private static int getId(String functionName) {
147 Integer id = (Integer)(idMap.get(functionName));
148
149 if (id == null)
150 throw new IllegalArgumentException("unknown set function " +
151 functionName);
152
153 return id.intValue();
154 }
155
156 /**
157 * Private helper that returns the argument type for the given standard
158 * function. Note that this doesn't check on the return value since the
159 * method always is called after getId, so we assume that the function
160 * is present.
161 */
162 private static String getArgumentType(String functionName) {
163 return (String)(typeMap.get(functionName));
164 }
165
166 /**
167 * Returns a <code>Set</code> containing all the function identifiers
168 * supported by this class.
169 *
170 * @return a <code>Set</code> of <code>String</code>s
171 */
172 public static Set getSupportedIdentifiers() {
173 return supportedIds;
174 }
175
176 /**
177 * Evaluates the function, using the specified parameters.
178 *
179 * @param inputs a <code>List</code> of <code>Evaluatable</code>
180 * objects representing the arguments passed to the function
181 * @param context an <code>EvaluationCtx</code> so that the
182 * <code>Evaluatable</code> objects can be evaluated
183 * @return an <code>EvaluationResult</code> representing the
184 * function's result
185 */
186 public EvaluationResult evaluate(List inputs, EvaluationCtx context) {
187
188 // Evaluate the arguments
189 AttributeValue [] argValues = new AttributeValue[inputs.size()];
190 EvaluationResult evalResult = evalArgs(inputs, context, argValues);
191 if (evalResult != null)
192 return evalResult;
193
194 // setup the two bags we'll be using
195 BagAttribute [] bags = new BagAttribute[2];
196 bags[0] = (BagAttribute)(argValues[0]);
197 bags[1] = (BagAttribute)(argValues[1]);
198
199 AttributeValue result = null;
200
201 switch(getFunctionId()) {
202 // *-at-least-one-member-of takes two bags of the same type and
203 // returns a boolean
204 case ID_BASE_AT_LEAST_ONE_MEMBER_OF:
205 // true if at least one element in the first argument is in the
206 // second argument (using the *-is-in semantics)
207
208 result = BooleanAttribute.getFalseInstance();
209 Iterator it = bags[0].iterator();
210
211 while (it.hasNext()) {
212 if (bags[1].contains((AttributeValue)(it.next()))) {
213 result = BooleanAttribute.getTrueInstance();
214 break;
215 }
216 }
217
218 break;
219
220 // *-set-equals takes two bags of the same type and returns
221 // a boolean
222 case ID_BASE_SUBSET:
223 // returns true if the first argument is a subset of the second
224 // argument (ie, all the elements in the first bag appear in
225 // the second bag) ... ignore all duplicate values in both
226 // input bags
227
228 boolean subset = bags[1].containsAll(bags[0]);
229 result = BooleanAttribute.getInstance(subset);
230
231 break;
232
233 // *-set-equals takes two bags of the same type and returns
234 // a boolean
235 case ID_BASE_SET_EQUALS:
236
237 // returns true if the two inputs contain the same elements
238 // discounting any duplicates in either input ... this is the same
239 // as applying the and function on the subset function with
240 // the two inputs, and then the two inputs reversed (ie, are the
241 // two inputs subsets of each other)
242
243 boolean equals = (bags[1].containsAll(bags[0]) &&
244 bags[0].containsAll(bags[1]));
245 result = BooleanAttribute.getInstance(equals);
246
247 break;
248 }
249
250 return new EvaluationResult(result);
251 }
252
253 }