Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/sun/xacml/finder/PolicyFinder.java


1   
2   /*
3    * @(#)PolicyFinder.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  import com.sun.xacml.PolicyReference;
41  
42  import com.sun.xacml.ctx.Status;
43  
44  import java.net.URI;
45  
46  import java.util.ArrayList;
47  import java.util.HashSet;
48  import java.util.Iterator;
49  import java.util.Set;
50  
51  import java.util.logging.Level;
52  import java.util.logging.Logger;
53  
54  
55  /**
56   * This class is used by the PDP to find all policies used in evaluation. A
57   * PDP is given a pre-configured <code>PolicyFinder</code> on construction.
58   * The <code>PolicyFinder</code> provides the functionality both to find
59   * policies based on a request (ie, retrieve policies and match against the
60   * target) and based on an idReference (as can be included in a PolicySet).
61   * <p>
62   * While this class is typically used by the PDP, it is intentionally
63   * designed to support stand-alone use, so it could be the base for a
64   * distributed service, or for some application that needs just this
65   * functionality. There is nothing in the <code>PolicyFinder</code that
66   * relies on the functionality in the PDP. An example of this is a PDP
67   * that offloads all policy work by passing requests to another server
68   * that does all the retrieval, and passes back the applicable policy.
69   * This would require custom code undefined in the XACML spec, but it would
70   * free up the server to focus on core policy processing.
71   * <p>
72   * Note that it is an error to have more than one top-level policy (as
73   * explained in the OnlyOneApplicable combining algorithm), so any module
74   * that is added to this finder will be evaluated each time a policy is
75   * requested. This means that you should think carefully about how many
76   * modules you include, and how they can cache policy data.
77   *
78   * @since 1.0
79   * @author Seth Proctor
80   */
81  public class PolicyFinder
82  {
83  
84      // all modules in this finder
85      private Set allModules;
86  
87      // all the request modules
88      private Set requestModules;
89  
90      // all the reference modules
91      private Set referenceModules;
92  
93      // the logger we'll use for all messages
94      private static final Logger logger =
95          Logger.getLogger(PolicyFinder.class.getName());
96  
97      /**
98       * Returns the unordered <code>Set</code> of modules used by this class
99       * to find policies.
100      *
101      * @return the set of modules used by this class
102      */
103     public Set getModules() {
104         return new HashSet(allModules);
105     }
106 
107     /**
108      * Sets the unordered <code>Set</code> of modules used by this class
109      * to find policies.
110      *
111      * @param modules the modules this class will use
112      */
113     public void setModules(Set modules) {
114         Iterator it = modules.iterator();
115 
116         allModules = new HashSet(modules);
117         requestModules = new HashSet();
118         referenceModules = new HashSet();
119 
120         while (it.hasNext()) {
121             PolicyFinderModule module = (PolicyFinderModule)(it.next());
122 
123             if (module.isRequestSupported())
124                 requestModules.add(module);
125 
126             if (module.isIdReferenceSupported())
127                 referenceModules.add(module);
128         }
129     }
130 
131     /**
132      *
133      */
134     public void init() {
135         logger.finer("Initializing PolicyFinder");
136 
137         Iterator it = allModules.iterator();
138 
139         while (it.hasNext()) {
140             PolicyFinderModule module = (PolicyFinderModule)(it.next());
141             module.init(this);
142         }
143     }
144 
145     /**
146      * Finds a policy based on a request's context. This may involve using
147      * the request data as indexing data to lookup a policy. This will always
148      * do a Target match to make sure that the given policy applies. If more
149      * than one applicable policy is found, this will return an error.
150      *
151      * @param context the representation of the request data
152      *
153      * @return the result of trying to find an applicable policy
154      */
155     public PolicyFinderResult findPolicy(EvaluationCtx context) {
156         PolicyFinderResult result = null;
157         Iterator it = requestModules.iterator();
158 
159         // look through all of the modules
160         while (it.hasNext()) {
161             PolicyFinderModule module = (PolicyFinderModule)(it.next());
162             PolicyFinderResult newResult = module.findPolicy(context);
163 
164             // if there was an error, we stop right away
165             if (newResult.indeterminate()) {
166                 if (logger.isLoggable(Level.INFO))
167                     logger.info("An error occured while trying to find a " +
168                                 "single applicable policy for a request: " +
169                                 newResult.getStatus().getMessage());
170 
171                 return newResult;
172             }
173 
174             // if we found a policy...
175             if (! newResult.notApplicable()) {
176                 // ...if we already had found a policy, this is an error...
177                 if (result != null) {
178                     logger.info("More than one top-level applicable policy " +
179                                 "for the request");
180 
181                     ArrayList code = new ArrayList();
182                     code.add(Status.STATUS_PROCESSING_ERROR);
183                     Status status = new Status(code, "too many applicable " +
184                                                "top-level policies");
185                     return new PolicyFinderResult(status);
186                 }
187 
188                 // ...otherwise we remember the result
189                 result = newResult;
190             }
191         }
192         
193         // if we got here then we didn't have any errors, so the only
194         // question is whether or not we found anything
195         if (result != null) {
196             return result;
197         } else {
198             logger.info("No applicable policies were found for the request");
199 
200             return new PolicyFinderResult();
201         }
202     }
203 
204     /**
205      * Finds a policy based on an id reference. This may involve using
206      * the reference as indexing data to lookup a policy. This will always
207      * do a Target match to make sure that the given policy applies. If more
208      * than one applicable policy is found, this will return an error.
209      *
210      * @param idReference the identifier used to resolve a policy
211      * @param type type of reference (policy or policySet) as identified by
212      *             the fields in <code>PolicyReference</code>
213      *
214      * @return the result of trying to find an applicable policy
215      *
216      * @throws IllegalArgumentException if <code>type</code> is invalid
217      */
218     public PolicyFinderResult findPolicy(URI idReference, int type)
219         throws IllegalArgumentException
220     {
221         PolicyFinderResult result = null;
222         Iterator it = referenceModules.iterator();
223 
224         if ((type != PolicyReference.POLICY_REFERENCE) &&
225             (type != PolicyReference.POLICYSET_REFERENCE))
226             throw new IllegalArgumentException("Unknown reference type");
227 
228         // look through all of the modules
229         while (it.hasNext()) {
230             PolicyFinderModule module = (PolicyFinderModule)(it.next());
231             PolicyFinderResult newResult = module.findPolicy(idReference,
232                                                              type);
233 
234             // if there was an error, we stop right away
235             if (newResult.indeterminate()) {
236                 if (logger.isLoggable(Level.INFO))
237                     logger.info("An error occured while trying to find the " +
238                                 "referenced policy " + idReference.toString() +
239                                 ": " + newResult.getStatus().getMessage());
240                 
241                 return newResult;
242             }
243 
244             // if we found a policy...
245             if (! newResult.notApplicable()) {
246                 // ...if we already had found a policy, this is an error...
247                 if (result != null) {
248                     if (logger.isLoggable(Level.INFO))
249                         logger.info("More than one policy applies for the " +
250                                     "reference: " + idReference.toString());
251                     ArrayList code = new ArrayList();
252                     code.add(Status.STATUS_PROCESSING_ERROR);
253                     Status status = new Status(code, "too many applicable " +
254                                                "top-level policies");
255                     return new PolicyFinderResult(status);
256                 }
257 
258                 // ...otherwise we remember the result
259                 result = newResult;
260             }
261         }
262         
263         // if we got here then we didn't have any errors, so the only
264         // question is whether or not we found anything
265         if (result != null) {
266             return result;
267         } else {
268             if (logger.isLoggable(Level.INFO))
269                 logger.info("No policies were resolved for the reference: " +
270                             idReference.toString());
271 
272             return new PolicyFinderResult();
273         }
274     }
275 
276 }