📄 basicevaluationctx.java
字号:
/*
* @(#)BasicEvaluationCtx.java
*
* Copyright 2004-2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistribution in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed or intended for use in
* the design, construction, operation or maintenance of any nuclear facility.
*/
package com.sun.xacml;
import com.sun.xacml.attr.AttributeDesignator;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.BagAttribute;
import com.sun.xacml.attr.DateAttribute;
import com.sun.xacml.attr.DateTimeAttribute;
import com.sun.xacml.attr.StringAttribute;
import com.sun.xacml.attr.TimeAttribute;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.ctx.Subject;
import com.sun.xacml.finder.AttributeFinder;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.Node;
/**
* A basic implementation of <code>EvaluationCtx</code> that is created from
* an XACML Request and falls back on an AttributeFinder if a requested
* value isn't available in the Request.
* <p>
* Note that this class can do some optional caching for current date, time,
* and dateTime values (defined by a boolean flag to the constructors). The
* XACML specification requires that these values always be available, but it
* does not specify whether or not they must remain constant over the course
* of an evaluation if the values are being generated by the PDP (if the
* values are provided in the Request, then obviously they will remain
* constant). The default behavior is for these environment values to be
* cached, so that (for example) the current time remains constant over the
* course of an evaluation.
*
* @since 1.2
* @author Seth Proctor
*/
public class BasicEvaluationCtx implements EvaluationCtx
{
// the finder to use if a value isn't in the request
private AttributeFinder finder;
// the DOM root the original RequestContext document
private Node requestRoot;
// the 4 maps that contain the attribute data
private HashMap subjectMap;
private HashMap resourceMap;
private HashMap actionMap;
private HashMap environmentMap;
// the resource and its scope
private AttributeValue resourceId;
private int scope;
// the cached current date, time, and datetime, which we may or may
// not be using depending on how this object was constructed
private DateAttribute currentDate;
private TimeAttribute currentTime;
private DateTimeAttribute currentDateTime;
private boolean useCachedEnvValues;
// the logger we'll use for all messages
private static final Logger logger =
Logger.getLogger(BasicEvaluationCtx.class.getName());
/**
* Constructs a new <code>BasicEvaluationCtx</code> based on the given
* request. The resulting context will cache current date, time, and
* dateTime values so they remain constant for this evaluation.
*
* @param request the request
*
* @throws ParsingException if a required attribute is missing, or if there
* are any problems dealing with the request data
*/
public BasicEvaluationCtx(RequestCtx request) throws ParsingException {
this(request, null, true);
}
/**
* Constructs a new <code>BasicEvaluationCtx</code> based on the given
* request.
*
* @param request the request
* @param cacheEnvValues whether or not to cache the current time, date,
* and dateTime so they are constant for the scope
* of this evaluation
*
* @throws ParsingException if a required attribute is missing, or if there
* are any problems dealing with the request data
*/
public BasicEvaluationCtx(RequestCtx request, boolean cacheEnvValues)
throws ParsingException
{
this(request, null, cacheEnvValues);
}
/**
* Constructs a new <code>BasicEvaluationCtx</code> based on the given
* request, and supports looking outside the original request for attribute
* values using the <code>AttributeFinder</code>. The resulting context
* will cache current date, time, and dateTime values so they remain
* constant for this evaluation.
*
* @param request the request
* @param finder an <code>AttributeFinder</code> to use in looking for
* attributes that aren't in the request
*
* @throws ParsingException if a required attribute is missing, or if there
* are any problems dealing with the request data
*/
public BasicEvaluationCtx(RequestCtx request, AttributeFinder finder)
throws ParsingException
{
this(request, finder, true);
}
/**
* Constructs a new <code>BasicEvaluationCtx</code> based on the given
* request, and supports looking outside the original request for attribute
* values using the <code>AttributeFinder</code>.
*
* @param request the request
* @param finder an <code>AttributeFinder</code> to use in looking for
* attributes that aren't in the request
* @param cacheEnvValues whether or not to cache the current time, date,
* and dateTime so they are constant for the scope
* of this evaluation
*
* @throws ParsingException if a required attribute is missing, or if there
* are any problems dealing with the request data
*/
public BasicEvaluationCtx(RequestCtx request, AttributeFinder finder,
boolean cacheEnvValues) throws ParsingException {
// keep track of the finder
this.finder = finder;
// remember the root of the DOM tree for XPath queries
requestRoot = request.getDocumentRoot();
// initialize the cached date/time values so it's clear we haven't
// retrieved them yet
this.useCachedEnvValues = cacheEnvValues;
currentDate = null;
currentTime = null;
currentDateTime = null;
// get the subjects, make sure they're correct, and setup tables
subjectMap = new HashMap();
setupSubjects(request.getSubjects());
// next look at the Resource data, which needs to be handled specially
resourceMap = new HashMap();
setupResource(request.getResource());
// setup the action data, which is generic
actionMap = new HashMap();
mapAttributes(request.getAction(), actionMap);
// finally, set up the environment data, which is also generic
environmentMap = new HashMap();
mapAttributes(request.getEnvironmentAttributes(), environmentMap);
}
/**
* This is quick helper function to provide a little structure for the
* subject attributes so we can search for them (somewhat) quickly. The
* basic idea is to have a map indexed by SubjectCategory that keeps
* Maps that in turn are indexed by id and keep the unique ctx.Attribute
* objects.
*/
private void setupSubjects(Set subjects) throws ParsingException {
// make sure that there is at least one Subject
if (subjects.size() == 0)
throw new ParsingException("Request must a contain subject");
// now go through the subject attributes
Iterator it = subjects.iterator();
while (it.hasNext()) {
Subject subject = (Subject)(it.next());
URI category = subject.getCategory();
Map categoryMap = null;
// see if we've already got a map for the category
if (subjectMap.containsKey(category)) {
categoryMap = (Map)(subjectMap.get(category));
} else {
categoryMap = new HashMap();
subjectMap.put(category, categoryMap);
}
// iterate over the set of attributes
Iterator attrIterator = subject.getAttributes().iterator();
while (attrIterator.hasNext()) {
Attribute attr = (Attribute)(attrIterator.next());
String id = attr.getId().toString();
if (categoryMap.containsKey(id)) {
// add to the existing set of Attributes w/this id
Set existingIds = (Set)(categoryMap.get(id));
existingIds.add(attr);
} else {
// this is the first Attr w/this id
HashSet newIds = new HashSet();
newIds.add(attr);
categoryMap.put(id, newIds);
}
}
}
}
/**
* This basically does the same thing that the other types need
* to do, except that we also look for a resource-id attribute, not
* because we're going to use, but only to make sure that it's actually
* there, and for the optional scope attribute, to see what the scope
* of the attribute is
*/
private void setupResource(Set resource) throws ParsingException {
mapAttributes(resource, resourceMap);
// make sure there resource-id attribute was included
if (! resourceMap.containsKey(RESOURCE_ID)) {
System.err.println("Resource must contain resource-id attr");
throw new ParsingException("resource missing resource-id");
} else {
// make sure there's only one value for this
Set set = (Set)(resourceMap.get(RESOURCE_ID));
if (set.size() > 1) {
System.err.println("Resource may contain only one " +
"resource-id Attribute");
throw new ParsingException("too many resource-id attrs");
} else {
// keep track of the resource-id attribute
resourceId = ((Attribute)(set.iterator().next())).getValue();
}
}
// see if a resource-scope attribute was included
if (resourceMap.containsKey(RESOURCE_SCOPE)) {
Set set = (Set)(resourceMap.get(RESOURCE_SCOPE));
// make sure there's only one value for resource-scope
if (set.size() > 1) {
System.err.println("Resource may contain only one " +
"resource-scope Attribute");
throw new ParsingException("too many resource-scope attrs");
}
Attribute attr = (Attribute)(set.iterator().next());
AttributeValue attrValue = attr.getValue();
// scope must be a string, so throw an exception otherwise
if (! attrValue.getType().toString().
equals(StringAttribute.identifier))
throw new ParsingException("scope attr must be a string");
String value = ((StringAttribute)attrValue).getValue();
if (value.equals("Immediate")) {
scope = SCOPE_IMMEDIATE;
} else if (value.equals("Children")) {
scope = SCOPE_CHILDREN;
} else if (value.equals("Descendants")) {
scope = SCOPE_DESCENDANTS;
} else {
System.err.println("Unknown scope type: " + value);
throw new ParsingException("invalid scope type: " + value);
}
} else {
// by default, the scope is always Immediate
scope = SCOPE_IMMEDIATE;
}
}
/**
* Generic routine for resource, attribute and environment attributes
* to build the lookup map for each. The Form is a Map that is indexed
* by the String form of the attribute ids, and that contains Sets at
* each entry with all attributes that have that id
*/
private void mapAttributes(Set input, Map output) {
Iterator it = input.iterator();
while (it.hasNext()) {
Attribute attr = (Attribute)(it.next());
String id = attr.getId().toString();
if (output.containsKey(id)) {
Set set = (Set)(output.get(id));
set.add(attr);
} else {
Set set = new HashSet();
set.add(attr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -