⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basicevaluationctx.java

📁 sunxacml源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:

/*
 * @(#)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 + -