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

Quick Search    Search Deep

Source code: com/sun/xacml/attr/AttributeDesignator.java


1   
2   /*
3    * @(#)AttributeDesignator.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.attr;
38  
39  import com.sun.xacml.EvaluationCtx;
40  import com.sun.xacml.Indenter;
41  import com.sun.xacml.MatchResult;
42  import com.sun.xacml.ParsingException;
43  import com.sun.xacml.TargetMatch;
44  
45  import com.sun.xacml.cond.Evaluatable;
46  import com.sun.xacml.cond.EvaluationResult;
47  
48  import com.sun.xacml.ctx.Attribute;
49  import com.sun.xacml.ctx.Status;
50  import com.sun.xacml.ctx.StatusDetail;
51  
52  import java.io.OutputStream;
53  import java.io.PrintStream;
54  
55  import java.net.URI;
56  
57  import java.util.ArrayList;
58  import java.util.Collections;
59  import java.util.Iterator;
60  import java.util.List;
61  
62  import java.util.logging.Level;
63  import java.util.logging.Logger;
64  
65  import org.w3c.dom.NamedNodeMap;
66  import org.w3c.dom.Node;
67  import org.w3c.dom.NodeList;
68  
69  
70  /**
71   * Represents all four kinds of Designators in XACML.
72   *
73   * @since 1.0
74   * @author Seth Proctor
75   */
76  public class AttributeDesignator implements Evaluatable
77  {
78  
79      /**
80       * Tells designator to search in the subject section of the request
81       */
82      public static final int SUBJECT_TARGET = 0;
83  
84      /**
85       * Tells designator to search in the resource section of the request
86       */
87      public static final int RESOURCE_TARGET = 1;
88  
89      /**
90       * Tells designator to search in the action section of the request
91       */
92      public static final int ACTION_TARGET = 2;
93  
94      /**
95       * Tells designator to search in the environment section of the request
96       */
97      public static final int ENVIRONMENT_TARGET = 3;
98  
99      /**
100      * The standard URI for the default subject category value
101      */
102     public static final String SUBJECT_CATEGORY_DEFAULT =
103         "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
104 
105     // helper array of strings
106     static final private String [] targetTypes = { "Subject", "Resource",
107                                                    "Action", "Environment" };
108 
109     // the type of designator we are
110     private int target;
111 
112     // required attributes
113     private URI type;
114     private URI id;
115 
116     // optional attribute
117     private URI issuer;
118 
119     // must resolution find something
120     private boolean mustBePresent;
121 
122     // if we're a subject this is the category
123     private URI subjectCategory;
124 
125     // the logger we'll use for all messages
126     private static final Logger logger =
127         Logger.getLogger(AttributeDesignator.class.getName());
128 
129     /**
130      * Creates a new <code>AttributeDesignator</code> without the optional
131      * issuer.
132      *
133      * @param target the type of designator as specified by the 4 member
134      *               *_TARGET fields
135      * @param type the data type resolved by this designator
136      * @param id the attribute id looked for by this designator
137      * @param mustBePresent whether resolution must find a value
138      */
139     public AttributeDesignator(int target, URI type, URI id,
140                                boolean mustBePresent) {
141         this(target, type, id, mustBePresent, null);
142     }
143 
144     /**
145      * Creates a new <code>AttributeDesignator</code> with the optional
146      * issuer.
147      *
148      * @param target the type of designator as specified by the 4 member
149      *               *_TARGET fields
150      * @param type the data type resolved by this designator
151      * @param id the attribute id looked for by this designator
152      * @param mustBePresent whether resolution must find a value
153      * @param issuer the issuer of the values to search for or null if no
154      *               issuer is specified
155      *
156      * @throws IllegalArgumentException if the input target isn't a valid value
157      */
158     public AttributeDesignator(int target, URI type, URI id,
159                                boolean mustBePresent, URI issuer) 
160         throws IllegalArgumentException{
161         
162         // check if input target is a valid value
163         if ((target != SUBJECT_TARGET) && 
164             (target != RESOURCE_TARGET) &&
165             (target != ACTION_TARGET) &&
166             (target != ENVIRONMENT_TARGET))
167             throw new IllegalArgumentException("Input target is not a valid" +
168                                                "value");        
169         this.target = target;
170         this.type = type;
171         this.id = id;
172         this.mustBePresent = mustBePresent;
173         this.issuer = issuer;
174 
175         subjectCategory = null;
176     }
177 
178     /**
179      * Sets the category if this is a SubjectAttributeDesignatorType
180      *
181      * @param category the subject category
182      */
183     public void setSubjectCategory(URI category) {
184         if (target == SUBJECT_TARGET)
185             subjectCategory = category;
186     }    
187 
188     /**
189      * Creates a new <code>AttributeDesignator</code> based on the DOM
190      * root of the XML data.
191      * 
192      * @param root the DOM root of the AttributeDesignatorType XML type
193      * @param target the type of designator to create as specified in the
194      *               four member *_TARGET fields
195      *
196      * @return the designator
197      *
198      * @throws ParsingException if the AttributeDesignatorType was invalid
199      */
200     public static AttributeDesignator getInstance(Node root, int target)
201         throws ParsingException
202     {
203         URI type = null;
204         URI id = null;
205         URI issuer = null;
206         boolean mustBePresent = false;
207         URI subjectCategory = null;
208 
209         NamedNodeMap attrs = root.getAttributes();
210 
211         try {
212             // there's always an Id
213             id = new URI(attrs.getNamedItem("AttributeId").getNodeValue());
214         } catch (Exception e) {
215             throw new ParsingException("Required AttributeId missing in " +
216                                        "AttributeDesignator", e);
217         }
218         
219         try {
220             // there's always a data type
221             type = new URI(attrs.getNamedItem("DataType").getNodeValue());
222         } catch (Exception e) {
223             throw new ParsingException("Required DataType missing in " +
224                                        "AttributeDesignator", e);
225         }
226         
227         try {
228             // there might be an issuer
229             Node node = attrs.getNamedItem("Issuer");
230             if (node != null)
231                 issuer = new URI(node.getNodeValue());
232 
233             // if it's for the Subject section, there's another attr
234             if (target == SUBJECT_TARGET) {
235                 Node scnode = attrs.getNamedItem("SubjectCategory");
236                 if (scnode != null)
237                     subjectCategory = new URI(scnode.getNodeValue());
238                 else
239                     subjectCategory = new URI(SUBJECT_CATEGORY_DEFAULT);
240             }
241 
242             // there might be a mustBePresent flag
243             node = attrs.getNamedItem("MustBePresent");
244             if (node != null)
245                 if (node.getNodeValue().equals("true"))
246                     mustBePresent = true;
247         } catch (Exception e) {
248             // this shouldn't ever happen, but in theory something could go
249             // wrong in the code in this try block
250             throw new ParsingException("Error parsing AttributeDesignator " +
251                                        "optional attributes", e);
252         }
253 
254         AttributeDesignator ad =
255             new AttributeDesignator(target, type, id, mustBePresent, issuer);
256         ad.setSubjectCategory(subjectCategory);
257 
258         return ad;
259     }
260 
261     /**
262      * Returns the type of this designator as specified by the *_TARGET
263      * fields.
264      *
265      * @return the designator type
266      */
267     public int getDesignatorType() {
268         return target;
269     }
270 
271     /**
272      * Returns the type of attribute that is resolved by this designator.
273      * While an AD will always return a bag, this method will always return
274      * the type that is stored in the bag.
275      *
276      * @return the attribute type
277      */
278     public URI getType() {
279         return type;
280     }
281 
282     /**
283      * Returns the AttributeId of the values resolved by this designator.
284      *
285      * @return identifier for the values to resolve
286      */
287     public URI getId() {
288         return id;
289     }
290 
291     /**
292      * Returns the subject category for this designator. If this is not a
293      * SubjectAttributeDesignator then this will always return null.
294      *
295      * @return the subject category or null if this isn't a
296      *         SubjectAttributeDesignator
297      */
298     public URI getCategory() {
299         return subjectCategory;
300     }
301 
302     /**
303      * Returns the issuer of the values resolved by this designator if
304      * specified.
305      *
306      * @return the attribute issuer or null if unspecified
307      */
308     public URI getIssuer() {
309         return issuer;
310     }
311 
312     /**
313      * Returns whether or not a value is required to be resolved by this
314      * designator.
315      *
316      * @return true if a value is required, false otherwise
317      */
318     public boolean mustBePresent() {
319         return mustBePresent;
320     }
321 
322     /**
323      * Always returns true, since a designator always returns a bag of
324      * attribute values.
325      *
326      * @return true
327      */
328     public boolean evaluatesToBag() {
329         return true;
330     }
331 
332     /**
333      * Always returns an empty list since designators never have children.
334      *
335      * @return an empty <code>List</code>
336      */
337     public List getChildren() {
338         return Collections.EMPTY_LIST;
339     }
340 
341     /**
342      * Evaluates the pre-assigned meta-data against the given context,
343      * trying to find some matching values.
344      *
345      * @param context the representation of the request
346      *
347      * @return a result containing a bag either empty because no values were
348      * found or containing at least one value, or status associated with an
349      * Indeterminate result
350      */
351     public EvaluationResult evaluate(EvaluationCtx context) {
352         EvaluationResult result = null;
353 
354         // look in the right section for some attribute values
355         switch(target) {
356         case SUBJECT_TARGET:
357             result = context.getSubjectAttribute(type, id,
358                                                  issuer, subjectCategory);
359             break;
360         case RESOURCE_TARGET:
361             result = context.getResourceAttribute(type, id, issuer);
362             break;
363         case ACTION_TARGET:
364             result = context.getActionAttribute(type, id, issuer);
365             break;
366         case ENVIRONMENT_TARGET:
367             result = context.getEnvironmentAttribute(type, id, issuer);
368             break;
369         }
370 
371         // if the lookup was indeterminate, then we return immediately
372         if (result.indeterminate())
373             return result;
374 
375         BagAttribute bag = (BagAttribute)(result.getAttributeValue());
376 
377         if (bag.isEmpty()) {
378             // if it's empty, this may be an error
379             if (mustBePresent) {
380                 if (logger.isLoggable(Level.INFO))
381                     logger.info("AttributeDesignator failed to resolve a " +
382                                 "value for a required attribute: " +
383                                 id.toString());
384 
385                 ArrayList code = new ArrayList();
386                 code.add(Status.STATUS_MISSING_ATTRIBUTE);
387                 
388                 String message = "Couldn't find " + targetTypes[target] +
389                     "AttributeDesignator attribute";
390 
391                 // Note that there is a bug in the XACML spec. You can't
392                 // specify an identifier without specifying acceptable
393                 // values. Until this is fixed, this code will only
394                 // return the status code, and not any hints about what
395                 // was missing
396 
397                 /*List attrs = new ArrayList();
398                   attrs.add(new Attribute(id,
399                   ((issuer == null) ? null :
400                   issuer.toString()),
401                   null, null));
402                   StatusDetail detail = new StatusDetail(attrs);*/
403 
404                 return new EvaluationResult(new Status(code, message));
405             }
406         }
407 
408         // if we got here the bag wasn't empty, or mustBePresent was false,
409         // so we just return the result
410         return result;
411     }
412 
413     /**
414      * Encodes this designator into its XML representation and
415      * writes this encoding to the given <code>OutputStream</code> with no
416      * indentation.
417      *
418      * @param output a stream into which the XML-encoded data is written
419      */
420     public void encode(OutputStream output) {
421         encode(output, new Indenter(0));
422     }
423 
424     /**
425      * Encodes this designator into its XML representation and
426      * writes this encoding to the given <code>OutputStream</code> with
427      * indentation.
428      *
429      * @param output a stream into which the XML-encoded data is written
430      * @param indenter an object that creates indentation strings
431      */
432     public void encode(OutputStream output, Indenter indenter) {
433         PrintStream out = new PrintStream(output);
434         String indent = indenter.makeString();
435 
436         String tag = "<" + targetTypes[target] + "AttributeDesignator";
437 
438         if ((target == SUBJECT_TARGET) && (subjectCategory != null))
439             tag += " SubjectCategory=\"" + subjectCategory.toString() + "\"";
440         
441         tag += " AttributeId=\"" + id.toString() + "\"";
442         tag += " DataType=\"" + type.toString() + "\"";
443 
444         if (issuer != null)
445             tag += " Issuer=\"" + issuer.toString() + "\"";
446 
447         if (mustBePresent)
448             tag += " MustBePresent=\"true\"";
449 
450         tag += "/>";
451 
452         out.println(indent + tag);
453     }
454 
455 }