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

Quick Search    Search Deep

Source code: com/sun/xacml/cond/FunctionBase.java


1   
2   /*
3    * @(#)FunctionBase.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.cond;
38  
39  import com.sun.xacml.EvaluationCtx;
40  
41  import com.sun.xacml.attr.AttributeValue;
42  
43  import com.sun.xacml.ctx.Status;
44  
45  import java.net.URI;
46  import java.net.URISyntaxException;
47  
48  import java.util.ArrayList;
49  import java.util.Arrays;
50  import java.util.Collection;
51  import java.util.Collections;
52  import java.util.HashMap;
53  import java.util.HashSet;
54  import java.util.Iterator;
55  import java.util.List;
56  import java.util.Map;
57  
58  
59  /**
60   * An abstract utility superclass for functions. Supplies several useful
61   * methods, making it easier to implement a <code>Function</code>. You can
62   * extend this class or implement <code>Function</code> directly, depending
63   * on your needs.
64   *
65   * @since 1.0
66   * @author Steve Hanna
67   * @author Seth Proctor
68   */
69  public abstract class FunctionBase implements Function
70  {
71      
72      /**
73       * The standard namespace where all the spec-defined functions live
74       */
75      public static final String FUNCTION_NS =
76          "urn:oasis:names:tc:xacml:1.0:function:";
77  
78      // A List used by makeProcessingError() to save some steps.
79      private static List processingErrList = null;
80  
81      // the name of this function
82      private String functionName;
83  
84      // the id used by this function
85      private int functionId;
86  
87      // the return type of this function, and whether it's a bag
88      private String returnType;
89      private boolean returnsBag;
90  
91      // flag that tells us which of the two constructors was used
92      private boolean singleType;
93      
94      // parameter data if we're only using a single type
95      private String paramType;
96      private boolean paramIsBag;
97      private int numParams;
98      private int minParams;
99      
100     // paramater data if we're using different types
101     private String [] paramTypes;
102     private boolean [] paramsAreBags;
103 
104     /**
105      * Constructor that sets up the function as having some number of
106      * parameters all of the same given type. If <code>numParams</code> is
107      * -1, then the length is variable
108      *
109      * @param functionName the name of this function as used by the factory
110      *                     and any XACML policies
111      * @param functionId an optional identifier that can be used by your
112      *                   code for convenience
113      * @param paramType the type of all parameters to this function, as used
114      *                  by the factory and any XACML documents
115      * @param paramIsBag whether or not every parameter is actually a bag
116      *                   of values
117      * @param numParams the number of parameters required by this function,
118      *                  or -1 if any number are allowed
119      * @param returnType the type returned by this function, as used by
120      *                   the factory and any XACML documents
121      * @param returnsBag whether or not this function returns a bag of values
122      */
123     public FunctionBase(String functionName, int functionId, String paramType,
124                         boolean paramIsBag, int numParams,
125                         String returnType, boolean returnsBag) {
126         this(functionName, functionId, returnType, returnsBag);
127 
128         singleType = true;
129 
130         this.paramType = paramType;
131         this.paramIsBag = paramIsBag;
132         this.numParams = numParams;
133         this.minParams = 0;
134     }
135 
136     /**
137      * Constructor that sets up the function as having some number of
138      * parameters all of the same given type. If <code>numParams</code> is
139      * -1, then the length is variable, and then <code>minParams</code> may
140      * be used to specify a minimum number of parameters. If
141      * <code>numParams</code> is not -1, then <code>minParams</code> is
142      * ignored.
143      *
144      * @param functionName the name of this function as used by the factory
145      *                     and any XACML policies
146      * @param functionId an optional identifier that can be used by your
147      *                   code for convenience
148      * @param paramType the type of all parameters to this function, as used
149      *                  by the factory and any XACML documents
150      * @param paramIsBag whether or not every parameter is actually a bag
151      *                   of values
152      * @param numParams the number of parameters required by this function,
153      *                  or -1 if any number are allowed
154      * @param minParams the minimum number of parameters required if 
155      *                  <code>numParams</code> is -1
156      * @param returnType the type returned by this function, as used by
157      *                   the factory and any XACML documents
158      * @param returnsBag whether or not this function returns a bag of values
159      */
160     public FunctionBase(String functionName, int functionId, String paramType,
161                         boolean paramIsBag, int numParams, int minParams,
162                         String returnType, boolean returnsBag) {
163         this(functionName, functionId, returnType, returnsBag);
164 
165         singleType = true;
166 
167         this.paramType = paramType;
168         this.paramIsBag = paramIsBag;
169         this.numParams = numParams;
170         this.minParams = minParams;
171     }
172 
173 
174     /**
175      * Constructor that sets up the function as having different types for
176      * each given parameter.
177      *
178      * @param functionName the name of this function as used by the factory
179      *                     and any XACML policies
180      * @param functionId an optional identifier that can be used by your
181      *                   code for convenience
182      * @param paramTypes the type of each parameter, in order, required by
183      *                   this function, as used by the factory and any XACML
184      *                    documents
185      * @param paramIsBag whether or not each parameter is actually a bag
186      *                   of values
187      * @param returnType the type returned by this function, as used by
188      *                   the factory and any XACML documents
189      * @param returnsBag whether or not this function returns a bag of values
190      */
191     public FunctionBase(String functionName, int functionId,
192                         String [] paramTypes, boolean [] paramIsBag,
193                         String returnType, boolean returnsBag) {
194         this(functionName, functionId, returnType, returnsBag);
195 
196         singleType = false;
197 
198         this.paramTypes = paramTypes;
199         this.paramsAreBags = paramIsBag;
200     }
201 
202     /**
203      * Constructor that sets up some basic values for functions that will
204      * take care of parameter checking on their own. If you use this
205      * constructor for your function class, then you must override the
206      * two check methods to make sure that parameters are correct.
207      *
208      * @param functionName the name of this function as used by the factory
209      *                     and any XACML policies
210      * @param functionId an optional identifier that can be used by your
211      *                   code for convenience
212      * @param returnType the type returned by this function, as used by
213      *                   the factory and any XACML documents
214      * @param returnsBag whether or not this function returns a bag of values
215      */
216     public FunctionBase(String functionName, int functionId,
217                         String returnType, boolean returnsBag) {
218         this.functionName = functionName;
219         this.functionId = functionId;
220         this.returnType = returnType;
221         this.returnsBag = returnsBag;
222     }
223 
224     /**
225      * Returns the full identifier of this function, as known by the factories.
226      *
227      * @return the function's identifier
228      *
229      * @throws IllegalArgumentException if the identifier isn't a valid URI
230      */
231     public URI getIdentifier() {
232         // this is to get around the exception handling problems, but may
233         // change if this code changes to include exceptions from the
234         // constructors
235         try {
236             return new URI(functionName);
237         } catch (URISyntaxException use) {
238             throw new IllegalArgumentException("invalid URI");
239         }
240     }
241 
242     /**
243      * Returns the name of the function to be handled by this particular
244      * object.
245      *
246      * @return the function name
247      */
248     public String getFunctionName() {
249         return functionName;
250     }
251 
252     /**
253      * Returns the Identifier of the function to be handled by this
254      * particular object.
255      *
256      * @return the function Id
257      */
258     public int getFunctionId() {
259         return functionId;
260     }
261 
262     /**
263      * Get the attribute type returned by this function.
264      *
265      * @return a <code>URI</code> indicating the attribute type
266      *         returned by this function
267      */
268     public URI getReturnType() {
269         try {
270             return new URI(returnType);
271         } catch (Exception e) {
272             return null;
273         }
274     }
275 
276     /**
277      * Returns true if this function returns a bag of values.
278      *
279      * @return true if the function returns a bag, false otherwise
280      */
281     public boolean returnsBag() {
282         return returnsBag;
283     }
284 
285     /**
286      * Returns the return type for this particular object.
287      *
288      * @return the return type
289      */
290     public String getReturnTypeAsString() {
291         return returnType;
292     }
293 
294     /**
295      * Create an <code>EvaluationResult</code> that indicates a
296      * processing error with the specified message. This method
297      * may be useful to subclasses.
298      *
299      * @param message a description of the error
300      *                (<code>null</code> if none)
301      * @return the desired <code>EvaluationResult</code>
302      */
303     protected static EvaluationResult makeProcessingError(String message) {
304         // Build up the processing error Status.
305         if (processingErrList == null) {
306             String [] errStrings = { Status.STATUS_PROCESSING_ERROR };
307             processingErrList = Arrays.asList(errStrings);
308         }
309         Status errStatus = new Status(processingErrList, message);
310         EvaluationResult processingError = new EvaluationResult(errStatus);
311 
312         return processingError;
313     }
314 
315     /**
316      * Evaluates each of the parameters, in order, filling in the argument
317      * array with the resulting values. If any error occurs, this method
318      * returns the error, otherwise null is returned, signalling that
319      * evaluation was successful for all inputs, and the resulting argument
320      * list can be used.
321      *
322      * @param params a <code>List</code> of <code>Evaluatable</code>
323      *               objects representing the parameters to evaluate
324      * @param context the representation of the request
325      * @param args an array as long as the params <code>List</code> that
326      *             will, on return, contain the <code>AttributeValue</code>s
327      *             generated from evaluating all parameters
328      *
329      * @return <code>null</code> if no errors were encountered, otherwise
330      *         an <code>EvaluationResult</code> representing the error
331      */
332     protected EvaluationResult evalArgs(List params, EvaluationCtx context,
333                                         AttributeValue [] args) {
334         Iterator it = params.iterator();
335         int index = 0;
336 
337         while (it.hasNext()) {
338             // get and evaluate the next parameter
339             Evaluatable eval = (Evaluatable)(it.next());
340             EvaluationResult result = eval.evaluate(context);
341 
342             // If there was an error, pass it back...
343             if (result.indeterminate())
344                 return result;
345 
346             // ...otherwise save it and keep going
347             args[index++] = result.getAttributeValue();
348         }
349 
350         // if no error occurred then we got here, so we return no errors
351         return null;
352     }
353     
354     /**
355      * Default handling of input checking. This does some simple checking
356      * based on the type of constructor used. If you need anything more
357      * complex, or if you used the simple constructor, then you must
358      * override this method.
359      *
360      * @param inputs a <code>List></code> of <code>Evaluatable</code>s
361      *
362      * @throws IllegalArgumentException if the inputs won't work
363      */
364     public void checkInputs(List inputs) throws IllegalArgumentException {
365         // first off, see what kind of function we are
366         if (singleType) {
367             // first, check the length of the inputs, if appropriate
368             if (numParams != -1) {
369                 if (inputs.size() != numParams)
370                     throw new IllegalArgumentException("wrong number of args" +
371                                                        " to " + functionName);
372             } else {
373                 if (inputs.size() < minParams)
374                     throw new IllegalArgumentException("not enough args" +
375                                                        " to " + functionName);
376             }
377 
378             // now, make sure everything is of the same, correct type
379             Iterator it = inputs.iterator();
380             while (it.hasNext()) {
381                 Evaluatable eval = (Evaluatable)(it.next());
382 
383                 if ((! eval.getType().toString().equals(paramType)) ||
384                     (eval.evaluatesToBag() != paramIsBag))
385                     throw new IllegalArgumentException("illegal parameter");
386             }
387         } else {
388             // first, check the length of the inputs
389             if (paramTypes.length != inputs.size())
390                 throw new IllegalArgumentException("wrong number of args" +
391                                                    " to " + functionName);
392             
393             // now, make sure everything is of the same, correct type
394             Iterator it = inputs.iterator();
395             int i = 0;
396             while (it.hasNext()) {
397                 Evaluatable eval = (Evaluatable)(it.next());
398 
399                 if ((! eval.getType().toString().equals(paramTypes[i])) ||
400                     (eval.evaluatesToBag() != paramsAreBags[i]))
401                     throw new IllegalArgumentException("illegal parameter");
402 
403                 i++;
404             }
405         }
406     }
407 
408     /**
409      * Default handling of input checking. This does some simple checking
410      * based on the type of constructor used. If you need anything more
411      * complex, or if you used the simple constructor, then you must
412      * override this method.
413      *
414      * @param inputs a <code>List></code> of <code>Evaluatable</code>s
415      *
416      * @throws IllegalArgumentException if the inputs won't work
417      */
418     public void checkInputsNoBag(List inputs) throws IllegalArgumentException {
419         // first off, see what kind of function we are
420         if (singleType) {
421             // first check to see if we need bags
422             if (paramIsBag)
423                 throw new IllegalArgumentException(functionName + "needs" +
424                                                    "bags on input");
425 
426             // now check on the length
427             if (numParams != -1) {
428                 if (inputs.size() != numParams)
429                     throw new IllegalArgumentException("wrong number of args" +
430                                                        " to " + functionName);
431             } else {
432                 if (inputs.size() < minParams)
433                     throw new IllegalArgumentException("not enough args" +
434                                                        " to " + functionName);
435             }
436 
437             // finally check param list
438             Iterator it = inputs.iterator();
439             while (it.hasNext()) {
440                 Evaluatable eval = (Evaluatable)(it.next());
441 
442                 if (! eval.getType().toString().equals(paramType))
443                     throw new IllegalArgumentException("illegal parameter");
444             }
445         } else {
446             // first, check the length of the inputs
447             if (paramTypes.length != inputs.size())
448                 throw new IllegalArgumentException("wrong number of args" +
449                                                    " to " + functionName);
450 
451             // now, make sure everything is of the same, correct type
452             Iterator it = inputs.iterator();
453             int i = 0;
454             while (it.hasNext()) {
455                 Evaluatable eval = (Evaluatable)(it.next());
456 
457                 if ((! eval.getType().toString().equals(paramTypes[i])) ||
458                     (paramsAreBags[i]))
459                     throw new IllegalArgumentException("illegal parameter");
460 
461                 i++;
462             }
463         }
464     }
465 
466 }