Source code: com/sun/xacml/finder/AttributeFinder.java
1
2 /*
3 * @(#)AttributeFinder.java
4 *
5 * Copyright 2003-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.finder;
38
39 import com.sun.xacml.EvaluationCtx;
40
41 import com.sun.xacml.attr.BagAttribute;
42
43 import com.sun.xacml.cond.EvaluationResult;
44
45 import java.net.URI;
46
47 import java.util.ArrayList;
48 import java.util.Iterator;
49 import java.util.List;
50 import java.util.Set;
51
52 import java.util.logging.Level;
53 import java.util.logging.Logger;
54
55 import org.w3c.dom.Node;
56
57
58 /**
59 * This class is used by the PDP to find attribute values that weren't
60 * originally supplied in the request. It can be called with the data supplied
61 * in <code>AttributeDesignator<code>s or <code>AttributeSelector</code>s.
62 * Because the modules in this finder may themselves need attribute data
63 * to search for attribute data, it's possible that the modules will look
64 * for values in the <code>EvaluationCtx</code>, which may in turn result
65 * in the invocation of this finder again, so module writers need to be
66 * careful about how they build their modules.
67 * <p>
68 * Note that unlike the PolicyFinder, this class doesn't always need to
69 * use every module it has to find a value. The ordering is maintained,
70 * however, so it will always start with the first module, and proceed
71 * in order until it finds a value or runs out of modules.
72 *
73 * @since 1.0
74 * @author Seth Proctor
75 */
76 public class AttributeFinder
77 {
78
79 // the list of all modules
80 private List allModules;
81
82 //
83 private List designatorModules;
84
85 //
86 private List selectorModules;
87
88 // the logger we'll use for all messages
89 private static final Logger logger =
90 Logger.getLogger(AttributeFinder.class.getName());
91
92 /**
93 * Default constructor.
94 */
95 public AttributeFinder() {
96 allModules = new ArrayList();
97 designatorModules = new ArrayList();
98 selectorModules = new ArrayList();
99 }
100
101 /**
102 * Returns the ordered <code>List</code> of modules used by this class
103 * to find attribute values.
104 *
105 * @return the list of modules used by this class
106 */
107 public List getModules() {
108 return new ArrayList(allModules);
109 }
110
111 /**
112 * Sets the ordered <code>List</code> of modules used by this class
113 * to find attribute values. The ordering will be maintained.
114 *
115 * @param modules the modules this class will use
116 */
117 public void setModules(List modules) {
118 Iterator it = modules.iterator();
119
120 allModules = new ArrayList(modules);
121 designatorModules = new ArrayList();
122 selectorModules = new ArrayList();
123
124 while (it.hasNext()) {
125 AttributeFinderModule module = (AttributeFinderModule)(it.next());
126
127 if (module.isDesignatorSupported())
128 designatorModules.add(module);
129
130 if (module.isSelectorSupported())
131 selectorModules.add(module);
132 }
133 }
134
135 /**
136 * Tries to find attribute values based on the given designator data.
137 * The result, if successful, will always contain a
138 * <code>BagAttribute</code>, even if only one value was found. If no
139 * values were found, but no other error occurred, an empty bag is
140 * returned.
141 *
142 * @param attributeType the datatype of the attributes to find
143 * @param attributeId the identifier of the attributes to find
144 * @param issuer the issuer of the attributes, or null if unspecified
145 * @param subjectCategory the category of the attribute if the
146 * designatorType is SUBJECT_TARGET, otherwise null
147 * @param context the representation of the request data
148 * @param designatorType the type of designator as named by the *_TARGET
149 * fields in <code>AttributeDesignator</code>
150 *
151 * @return the result of attribute retrieval, which will be a bag of
152 * attributes or an error
153 */
154 public EvaluationResult findAttribute(URI attributeType, URI attributeId,
155 URI issuer, URI subjectCategory,
156 EvaluationCtx context,
157 int designatorType) {
158 Iterator it = designatorModules.iterator();
159
160 // go through each module in order
161 while (it.hasNext()) {
162 AttributeFinderModule module = (AttributeFinderModule)(it.next());
163
164 // see if the module supports this type
165 Set types = module.getSupportedDesignatorTypes();
166 if ((types == null) || (types.
167 contains(new Integer(designatorType)))) {
168 // see if the module can find an attribute value
169 EvaluationResult result =
170 module.findAttribute(attributeType, attributeId, issuer,
171 subjectCategory, context,
172 designatorType);
173
174 // if there was an error, we stop right away
175 if (result.indeterminate()) {
176 if (logger.isLoggable(Level.INFO))
177 logger.info("Error while trying to resolve values: " +
178 result.getStatus().getMessage());
179 return result;
180 }
181
182 // if the result wasn't empty, then return the result
183 BagAttribute bag = (BagAttribute)(result.getAttributeValue());
184 if (! bag.isEmpty())
185 return result;
186 }
187 }
188
189 // if we got here then there were no errors but there were also no
190 // matches, so we have to return an empty bag
191 if (logger.isLoggable(Level.INFO))
192 logger.info("Failed to resolve any values for " +
193 attributeId.toString());
194
195 return new EvaluationResult(BagAttribute.
196 createEmptyBag(attributeType));
197 }
198
199 /**
200 * Tries to find attribute values based on the given selector data.
201 * The result, if successful, must always contain a
202 * <code>BagAttribute</code>, even if only one value was found. If no
203 * values were found, but no other error occurred, an empty bag is
204 * returned.
205 *
206 * @param contextPath the XPath expression to search against
207 * @param namespaceNode the DOM node defining namespace mappings to use,
208 * or null if mappings come from the context root
209 * @param attributeType the datatype of the attributes to find
210 * @param context the representation of the request data
211 * @param xpathVersion the XPath version to use
212 *
213 * @return the result of attribute retrieval, which will be a bag of
214 * attributes or an error
215 */
216 public EvaluationResult findAttribute(String contextPath,
217 Node namespaceNode,
218 URI attributeType,
219 EvaluationCtx context,
220 String xpathVersion) {
221 Iterator it = selectorModules.iterator();
222
223 // go through each module in order
224 while (it.hasNext()) {
225 AttributeFinderModule module = (AttributeFinderModule)(it.next());
226
227 // see if the module can find an attribute value
228 EvaluationResult result =
229 module.findAttribute(contextPath, namespaceNode, attributeType,
230 context, xpathVersion);
231
232 // if there was an error, we stop right away
233 if (result.indeterminate()) {
234 if (logger.isLoggable(Level.INFO))
235 logger.info("Error while trying to resolve values: " +
236 result.getStatus().getMessage());
237 return result;
238 }
239
240 // if the result wasn't empty, then return the result
241 BagAttribute bag = (BagAttribute)(result.getAttributeValue());
242 if (! bag.isEmpty())
243 return result;
244 }
245
246 // if we got here then there were no errors but there were also no
247 // matches, so we have to return an empty bag
248 if (logger.isLoggable(Level.INFO))
249 logger.info("Failed to resolve any values for " + contextPath);
250
251 return new EvaluationResult(BagAttribute.
252 createEmptyBag(attributeType));
253 }
254
255 }