Package org.jboss.security.xacml.sunxacml

Source Code of org.jboss.security.xacml.sunxacml.TargetMatch

/*
* @(#)TargetMatch.java
*
* Copyright 2003-2005 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 org.jboss.security.xacml.sunxacml;





import java.io.OutputStream;
import java.io.PrintStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jboss.security.xacml.sunxacml.attr.AttributeDesignator;
import org.jboss.security.xacml.sunxacml.attr.AttributeFactory;
import org.jboss.security.xacml.sunxacml.attr.AttributeSelector;
import org.jboss.security.xacml.sunxacml.attr.AttributeValue;
import org.jboss.security.xacml.sunxacml.attr.BagAttribute;
import org.jboss.security.xacml.sunxacml.attr.BooleanAttribute;
import org.jboss.security.xacml.sunxacml.cond.Evaluatable;
import org.jboss.security.xacml.sunxacml.cond.EvaluationResult;
import org.jboss.security.xacml.sunxacml.cond.Function;
import org.jboss.security.xacml.sunxacml.cond.FunctionFactory;
import org.jboss.security.xacml.sunxacml.cond.FunctionTypeException;
import org.jboss.security.xacml.sunxacml.ctx.Status;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


/**
* Represents the SubjectMatch, ResourceMatch, ActionMatch, or EnvironmentMatch
* (in XACML 2.0 and later) XML types in XACML, depending on the value of the
* type field. This is the part of the Target that actually evaluates whether
* the specified attribute values in the Target match the corresponding
* attribute values in the request context.
*
* @since 1.0
* @author Seth Proctor
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public class TargetMatch
{

    /**
     * An integer value indicating that this class represents a SubjectMatch
     */
    public static final int SUBJECT = 0;

    /**
     * An integer value indicating that this class represents a ResourceMatch
     */
    public static final int RESOURCE = 1;

    /**
     * An integer value indicating that this class represents an ActionMatch
     */
    public static final int ACTION = 2;

    /**
     * An integer value indicating that this class represents an
     * EnvironmentMatch
     */
    public static final int ENVIRONMENT = 3;
   
    /**
     * Mapping from the 4 match types to their string representations
     */
    public static final String [] NAMES = { "Subject", "Resource", "Action",
                                            "Environment" };

    // the type of this target match
    private int type;

    // the function used for matching
    private Function function;

    // the designator or selector
    private Evaluatable eval;

    // the value
    private AttributeValue attrValue;

    /**
     * Constructor that creates a <code>TargetMatch</code> from components.
     *
     * @param type an integer indicating whether this class represents a
     *             SubjectMatch, ResourceMatch, or ActionMatch
     * @param function the <code>Function</code> that represents the MatchId
     * @param eval the <code>AttributeDesignator</code> or
     *             <code>AttributeSelector</code> to be used to select
     *             attributes from the request context
     * @param attrValue the <code>AttributeValue</code> to compare against
     *
     * @throws IllegalArgumentException if the input type isn't a valid value
     */
    public TargetMatch(int type, Function function, Evaluatable eval,
                       AttributeValue attrValue)
        throws IllegalArgumentException {

        // check if input type is a valid value
        if ((type != SUBJECT) &&
            (type != RESOURCE) &&
            (type != ACTION) &&
            (type != ENVIRONMENT))
            throw new IllegalArgumentException("Unknown TargetMatch type");

        this.type = type;
        this.function = function;
        this.eval = eval;
        this.attrValue = attrValue;
    }

    /**
     * Creates a <code>TargetMatch</code> by parsing a node, using the
     * input prefix to determine whether this is a SubjectMatch, ResourceMatch,
     * or ActionMatch.
     *
     * @deprecated As of 2.0 you should avoid using this method and should
     *             instead use the version that takes a
     *             <code>PolicyMetaData</code> instance. This method will
     *             only work for XACML 1.x policies.
     *
     * @param root the node to parse for the <code>TargetMatch</code>
     * @param prefix a String indicating what type of <code>TargetMatch</code>
     *               to instantiate (Subject, Resource, or Action)
     * @param xpathVersion the XPath version to use in any selectors, or
     *                     null if this is unspecified (ie, not supplied in
     *                     the defaults section of the policy)
     *
     * @return a new <code>TargetMatch</code> constructed by parsing
     *
     * @throws ParsingException if there was an error during parsing
     * @throws IllegalArgumentException if the input prefix isn't a valid value
     */
    public static TargetMatch getInstance(Node root, String prefix,
                                          String xpathVersion)
        throws ParsingException, IllegalArgumentException
    {
        int i = 0;
        while ((i < NAMES.length) && (! NAMES[i].equals(prefix)))
            i++;

        if (i == NAMES.length)
            throw new IllegalArgumentException("Unknown TargetMatch type");

        return getInstance(root, i,
                           new PolicyMetaData(
                                   PolicyMetaData.XACML_1_0_IDENTIFIER,
                                   xpathVersion));
    }

    /**
     * Creates a <code>TargetMatch</code> by parsing a node, using the
     * input prefix to determine whether this is a SubjectMatch, ResourceMatch,
     * or ActionMatch.
     *
     * @param root the node to parse for the <code>TargetMatch</code>
     * @param matchType the type of <code>TargetMatch</code> as specified by
     *                  the SUBJECT, RESOURCE, ACTION, or ENVIRONMENT fields
     * @param metaData the policy's meta-data
     *
     * @return a new <code>TargetMatch</code> constructed by parsing
     *
     * @throws ParsingException if there was an error during parsing
     */
    public static TargetMatch getInstance(Node root, int matchType,
                                          PolicyMetaData metaData)
        throws ParsingException
    {
        Function function;
        Evaluatable eval = null;
        AttributeValue attrValue = null;

        AttributeFactory attrFactory = AttributeFactory.getInstance();

        // get the function type, making sure that it's really a correct
        // Target function
        String funcName = root.getAttributes().
            getNamedItem("MatchId").getNodeValue();
        FunctionFactory factory = FunctionFactory.getTargetInstance();
        try {
            URI funcId = new URI(funcName);
            function = factory.createFunction(funcId);
        } catch (URISyntaxException use) {
            throw new ParsingException("Error parsing TargetMatch", use);
        } catch (UnknownIdentifierException uie) {
            throw new ParsingException("Unknown MatchId", uie);
        } catch (FunctionTypeException fte) {
            // try to create an abstract function
            try {
                URI funcId = new URI(funcName);
                function = factory.createAbstractFunction(funcId, root);
            } catch (Exception e) {
                // any exception here is an error
                throw new ParsingException("invalid abstract function", e);
            }
        }

        // next, get the designator or selector being used, and the attribute
        // value paired with it
        NodeList nodes = root.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            String name = SunxacmlUtil.getNodeName(node);

            if (name.equals(NAMES[matchType] + "AttributeDesignator")) {
                eval = AttributeDesignator.getInstance(node, matchType,
                                                       metaData);
            } else if (name.equals("AttributeSelector")) {
                eval = AttributeSelector.getInstance(node, metaData);
            } else if (name.equals("AttributeValue")) {
                try {
                    attrValue = attrFactory.createValue(node);
                } catch (UnknownIdentifierException uie) {
                    throw new ParsingException("Unknown Attribute Type", uie);
                }
            }
        }

        // finally, check that the inputs are valid for this function
        List inputs = new ArrayList();
        inputs.add(attrValue);
        inputs.add(eval);
        function.checkInputsNoBag(inputs);

        return new TargetMatch(matchType, function, eval, attrValue);
    }

    /**
     * Returns the type of this <code>TargetMatch</code>, either
     * <code>SUBJECT</code>, <code>RESOURCE</code>, <code>ACTION</code>, or
     * <code>ENVIRONMENT</code>.
     *
     * @return the type
     */
    public int getType() {
        return type;
    }

    /**
     * Returns the <code>Function</code> used to do the matching.
     *
     * @return the match function
     */
    public Function getMatchFunction() {
        return function;
    }

    /**
     * Returns the <code>AttributeValue</code> used by the matching function.
     *
     * @return the <code>AttributeValue</code> for the match
     */
    public AttributeValue getMatchValue() {
        return attrValue;
    }

    /**
     * Returns the <code>AttributeDesignator</code> or
     * <code>AttributeSelector</code> used by the matching function.
     *
     * @return the designator or selector for the match
     */
    public Evaluatable getMatchEvaluatable() {
        return eval;
    }

    /**
     * Determines whether this <code>TargetMatch</code> matches
     * the input request (whether it is applicable)
     *
     * @param context the representation of the request
     *
     * @return the result of trying to match the TargetMatch and the request
     */
    public MatchResult match(EvaluationCtx context) {
        // start by evaluating the AD/AS
        EvaluationResult result = eval.evaluate(context);
       
        if (result.indeterminate()) {
            // in this case, we don't ask the function for anything, and we
            // simply return INDETERMINATE
            return new MatchResult(MatchResult.INDETERMINATE,
                                   result.getStatus());
        }

        // an AD/AS will always return a bag
        BagAttribute bag = (BagAttribute)(result.getAttributeValue());

        if (! bag.isEmpty()) {
            // we got back a set of attributes, so we need to iterate through
            // them, seeing if at least one matches
            Iterator it = bag.iterator();
            boolean atLeastOneError = false;
            Status firstIndeterminateStatus = null;

            while (it.hasNext()) {
                ArrayList inputs = new ArrayList();

                inputs.add(attrValue);
                inputs.add(it.next());

                // do the evaluation
                MatchResult match = evaluateMatch(inputs, context);
               
                // we only need one match for this whole thing to match
                if (match.getResult() == MatchResult.MATCH)
                    return match;

                // if it was INDETERMINATE, we want to remember for later
                if (match.getResult() == MatchResult.INDETERMINATE) {
                    atLeastOneError = true;

                    // there are no rules about exactly what status data
                    // should be returned here, so like in the combining
                    // algs, we'll just track the first error
                    if (firstIndeterminateStatus == null)
                        firstIndeterminateStatus = match.getStatus();
                }
            }

            // if we got here, then nothing matched, so we'll either return
            // INDETERMINATE or NO_MATCH
            if (atLeastOneError)
                return new MatchResult(MatchResult.INDETERMINATE,
                                       firstIndeterminateStatus);
            else
                return new MatchResult(MatchResult.NO_MATCH);

        } else {
            // this is just an optimization, since the loop above will
            // actually handle this case, but this is just a little
            // quicker way to handle an empty bag
            return new MatchResult(MatchResult.NO_MATCH);
        }
    }
   
    /**
     * Private helper that evaluates an individual match.
     */
    private MatchResult evaluateMatch(List inputs, EvaluationCtx context) {
        // first off, evaluate the function
        EvaluationResult result = function.evaluate(inputs, context);

        // if it was indeterminate, then that's what we return immediately
        if (result.indeterminate())
            return new MatchResult(MatchResult.INDETERMINATE,
                                   result.getStatus());

        // otherwise, we figure out if it was a match
        BooleanAttribute bool = (BooleanAttribute)(result.getAttributeValue());

        if (bool.getValue())
            return new MatchResult(MatchResult.MATCH);
        else
            return new MatchResult(MatchResult.NO_MATCH);
    }

    /**
     * Encodes this <code>TargetMatch</code> into its XML representation and
     * writes this encoding to the given <code>OutputStream</code> with no
     * indentation.
     *
     * @param output a stream into which the XML-encoded data is written
     */
    public void encode(OutputStream output) {
        encode(output, new Indenter(0));
    }

    /**
     * Encodes this <code>TargetMatch</code> into its XML representation and
     * writes this encoding to the given <code>OutputStream</code> with
     * indentation.
     *
     * @param output a stream into which the XML-encoded data is written
     * @param indenter an object that creates indentation strings
     */
    public void encode(OutputStream output, Indenter indenter) {
        PrintStream out = new PrintStream(output);
        String indent = indenter.makeString();
        String tagName = NAMES[type] + "Match";

        out.println(indent + "<" + tagName + " MatchId=\"" +
                    function.getIdentifier().toString()+ "\">");
        indenter.in();

        attrValue.encode(output, indenter);
        eval.encode(output, indenter);
       
        indenter.out();
        out.println(indent + "</" + tagName + ">");
    }

}
TOP

Related Classes of org.jboss.security.xacml.sunxacml.TargetMatch

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.